首页 > 代码库 > 百度之星2014初赛第二场

百度之星2014初赛第二场

A. Scenic Popularity

http://acm.hdu.edu.cn/showproblem.php?pid=4831

思路:景点区会控制休息区的Hot值,我们建立休息区到它最近的景点区的关系,注意处理冲突。

查询和修改都暴力进行,预处理关系,从左到右,然后从右到左遍历一遍即可,更新时候,从被修改的p位置,向两边,与p有关的休息区进行更新。总的时间复杂度O(T*n*K),10^8左右,不到1s可以解决。

const int maxn = 10000;
const int maxh = 100000;

struct node {
    int pos; //位置
    int hot; //hot值
    bool isRest; //是否是休息区
    int control[2]; //休息区所属的风景区下标
}elem[maxn];


void run() {
    int t, n, p, v;
    scanf("%d", &t);
    FOR(Cas, 1, t) {
        scanf("%d", &n);
        FOR(i, 0, n - 1) {
            scanf("%d%d", &p,&v);
            elem[i].pos = p;
            elem[i].hot = v;
            elem[i].isRest = (v == 0) ? true : false;
            memset(elem[i].control, -1, sizeof(elem[i].control));
        }
        //Left->Right
        int lMark = -1;
        FOR(i, 0, n - 1) {
            if (!elem[i].isRest) {
                lMark = i;
            } else if (lMark != -1 && elem[i].isRest) {
                elem[i].control[0] = lMark;
                elem[i].hot = elem[lMark].hot;
            }
        }
        //Right->Left
        int rMark = -1;
        FORD(i, n-1, 0) {
            if (!elem[i].isRest) {
                rMark = i;
            } else if (rMark != -1 && elem[i].isRest) {

                if (elem[i].control[0] == -1) {//未被控制的休息点
                    elem[i].control[0] = rMark;
                    elem[i].hot = elem[rMark].hot;
                } else {
                    int lMark = elem[i].control[0];
                    int flag = abs(elem[rMark].pos - elem[i].pos) - abs(elem[lMark].pos - elem[i].pos);//flag 1:L -1:R 0:E
                    if (flag != 0) { 
                        elem[i].control[0] = flag > 0 ? lMark : rMark; 
                        elem[i].control[1] = -1;
                        elem[i].hot = elem[elem[i].control[0]].hot;
                    } else {
                        elem[i].control[0] = lMark;
                        elem[i].control[1] = rMark;
                        elem[i].hot = max(elem[lMark].hot, elem[rMark].hot);
                    }
                }
            }
        }
        //query
        int query;
        scanf("%d", &query);
        printf("Case #%d:\n", Cas);
        FOR(i, 1, query) {
            char ch[10];
            scanf("%s", ch);
            if (!strcmp(ch, "Q")) {
                scanf("%d", &v);
                int ans = 0;
                FOR(idx, 0, n - 1) {
                    if (elem[idx].hot <= v) ans++;
                }
                printf("%d\n", ans);
            } else {
                scanf("%d%d", &p, &v);
                elem[p].hot = v;
                int idx;
                //Left update
                for (idx = p - 1; idx >= 0 && elem[idx].isRest && ((elem[idx].control[0] == p) || (elem[idx].control[1] == p)); idx--) {
                    elem[idx].hot = elem[elem[idx].control[0]].hot;
                    if (elem[idx].control[1] != -1) {
                        elem[idx].hot = max(elem[idx].hot, elem[elem[idx].control[1]].hot);
                    }
                }
                //Right update
                for (idx = p + 1; idx < n && elem[idx].isRest && ((elem[idx].control[0] == p) || (elem[idx].control[1] == p)); idx++) {
                    elem[idx].hot = elem[elem[idx].control[0]].hot;
                    if (elem[idx].control[1] != -1) {
                        elem[idx].hot = max(elem[idx].hot, elem[elem[idx].control[1]].hot);
                    }
                }
            }
        }
    }
}
View Code

 

B.

 

C.

 

D. JZP Set

http://acm.hdu.edu.cn/showproblem.php?pid=4834

思路:定义要求的函数为g(n), 枚举前几项,然后OEIS,找到 http://oeis.org/A124197,

我们可以得到,g(n) = n + 1 + f(1) + f(2) + ... + f(n-1)

那么f(n) = f(n-1) + h(n);

h(n)是整数n的奇数因子的个数,那么

h(n) = d(n),n为奇数

h(n) = d(n) - d(n/2),n为偶数

d(n)是整数n的因子个数。

使用打表,将整数n进行质因子分解,2^p1*3^p2*5*p3....,n的因子个数为(p1+1)(p2+1)(...),这里打一个素数表然后分解

得到d(n),就可以向上迭代得到g(n),n数据范围为10^7,最后结果注意要是64bit。注意因子分解时候进行时间优化,以及整体的空间优化。

 

const int maxn = 10000000;
int d[maxn + 5];
int64 f, g[maxn + 5];
int prime[maxn/5];
bool isPrime[maxn + 5];


void run()
{
    int i, j;
    isPrime[1] = isPrime[1] = 1;
    for (i = 2; i <= maxn; ++i) {
        if (!isPrime[i]) {
            for (j = i + i; j <= maxn; j+=i) {
                isPrime[j] = 1;
            }
        }
    }

    int cnt = 0;
    for (i = 2; i <= maxn; i++) {
        if (!isPrime[i])
            prime[cnt++] = i;
    }
    d[1] = 1;
    for (i = 2; i <= maxn; ++i) {
        int val = i, ans = 1;
        if (!isPrime[i]) d[i] = 2;
        else {
            for (j = 0; j < cnt; ++j) {
                if (prime[j] > val) break;
                int tmp = 0;
                while (val % prime[j] == 0) {
                    tmp++;
                    val /= prime[j];
                }
                ans *= (tmp + 1);
                if (!isPrime[val]) {
                    ans <<= 1;
                    break;
                }
            }
            d[i] = ans;
        }
    }


    f = 1;
    g[1] = 2;
    for (i = 2; i <= maxn; ++i) {
        g[i] = g[i - 1] + f + 1;
        f += ((i & 0x01) ? d[i] : (d[i] - d[i >> 1]));
    }

    int t, e;
    scanf("%d", &t);
    for (int nt = 1; nt <= t; ++nt) {
        scanf("%d", &e);
        printf("Case #%d:\n%I64d\n", nt, g[e]);
    }

}
View Code