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]);
}}