POJ 2886 Who Gets the Most Candies?
2012-04-05 23:56
387 查看
POJ_2886
由于N比较大,如果像模拟约瑟夫环那样用链表模拟的话,每次查找操作的复杂度是O(N)的,时间上是不允许的。但如果我们用线段树来直接求每次轮到谁的话,每次就只需要O(logN)的时间了。
于是大概思路就是每次都通过线段树查找相应的位置,然后计算一下F(p)的值并更新结果即可。
由于N比较大,如果像模拟约瑟夫环那样用链表模拟的话,每次查找操作的复杂度是O(N)的,时间上是不允许的。但如果我们用线段树来直接求每次轮到谁的话,每次就只需要O(logN)的时间了。
于是大概思路就是每次都通过线段树查找相应的位置,然后计算一下F(p)的值并更新结果即可。
#include<stdio.h> #include<string.h> #include<math.h> #define MAXD 500010 int N, M, K, P, tree[4 * MAXD], card[MAXD], isprime[MAXD], prime[MAXD]; char name[MAXD][15]; void update(int cur) { tree[cur] = tree[2 * cur] + tree[2 * cur + 1]; } void build(int cur, int x, int y) { int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1; if(x == y) { tree[cur] = 1; return ; } build(ls, x, mid); build(rs, mid + 1, y); update(cur); } void init() { int i; for(i = 1; i <= N; i ++) scanf("%s%d", name[i], &card[i]); build(1, 1, N); } void reset(int cur, int x, int y, int k) { int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1; if(x == y) { tree[cur] = 0; return ; } if(k <= mid) reset(ls, x, mid, k); else reset(rs, mid + 1, y, k); update(cur); } void getf(int turn, int x, int &ans, int &ansx) { int i, j, res = 1; for(i = 0; prime[i] <= turn; i ++) if(turn % prime[i] == 0) { j = 1; while(turn % prime[i] == 0) turn /= prime[i], ++ j; res *= j; } if(turn != 1) res *= 2; if(res > ans) ans = res, ansx = x; } int sum(int cur, int x, int y, int t) { int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1; if(y <= t) return tree[cur]; if(t <= mid) return sum(ls, x, mid, t); else return tree[ls] + sum(rs, mid + 1, y, t); } int Search(int cur, int x, int y, int k) { int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1; if(x == y) return x; if(k <= tree[ls]) return Search(ls, x, mid, k); else return Search(rs, mid + 1, y, k - tree[ls]); } void change(int &x) { int i, j, k = card[x], n; n = sum(1, 1, N, x); if(k < 0) { k = (-k - 1) % tree[1] + 1; if(n < k) x = Search(1, 1, N, tree[1] - k + n + 1); else x = Search(1, 1, N, n - k + 1); } else { k = (k - 1) % tree[1] + 1; if(tree[1] - n < k) x = Search(1, 1, N, k - tree[1] + n); else x = Search(1, 1, N, n + k); } } void solve() { int i, j, x = K, ans = 0, ansx; for(i = 1; i <= N; i ++) { reset(1, 1, N, x); getf(i, x, ans, ansx); if(i != N) change(x); } printf("%s %d\n", name[ansx], ans); } void prepare() { int i, j, k; memset(isprime, -1, sizeof(isprime)); k = sqrt(500000 + 0.5), P = 0; for(i = 2; i <= k; i ++) if(isprime[i]) { prime[P ++] = i; for(j = i * i; j <= k; j += i) isprime[j] = 0; } prime[P ++] = 1000003; } int main() { prepare(); while(scanf("%d%d", &N, &K) == 2) { init(); solve(); } return 0; }
相关文章推荐
- poj 2886 Who Gets the Most Candies?(线段树)
- Who Gets the Most Candies? - POJ 2886 线段树
- poj 2886 Who Gets the Most Candies?(线段树单点更新+反素数)真难。。。
- POJ 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies? (线段树)
- POJ 2886 Who Gets the Most Candies?(线段树·约瑟夫环)
- POJ - 2886 Who Gets the Most Candies?(线段树)
- POJ 2886 Who Gets the Most Candies?
- Poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies? 线段树
- POJ 2886 Who Gets the Most Candies?(线段树)
- 挑战练习题3.3 POJ 2886 Who Gets the Most Candies? 树状数组
- poj 2886 Who Gets the Most Candies?(线段树、反素数)
- 线段树(单点更新) POJ 2886 Who Gets the Most Candies?
- poj 2886 Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies? (线段树)
- POJ-2886 Who Gets the Most Candies? 线段树 + 反素数
- POJ2886-Who Gets the Most Candies?
- POJ 2886 Who Gets the Most Candies?【线段树单点更新+反素数打表】【好题】
- poj 2886 Who Gets the Most Candies?