POJ 2886 Who Gets the Most Candies? (树状数组)
感觉树状数组要比线段树优雅。。。反素数打表什么的都搞好了,就是从当前位置推下一个位置的公式没搞出来,后来看得别人的。。。
if(p[now].x > 0) nxt = (nxt - 1 + p[now].x)%leave;
else nxt = ((nxt + p[now].x)%leave + leave)%leave;
然后在树状数组里找第nxt大的数(二分)。。。
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; const int N = 500010; const int M = 1024; struct node { int a, b; node() {} node(int x, int y) : a(x), b(y) {} bool operator < (const node cmp) const { return b < cmp.b; } }f[M]; bool vis[M]; int prime[M]; int cnt, num; void get_prime() { int i, j; CL(vis, true); for(i = 2; i < M; ++i) { for(j = i*i; j < M; j += i) { vis[j] = false; } } cnt = 0; for(i = 2; i < M; ++i) { if(vis[i]) prime[cnt++] = i; } } void solve(int pnum, int val, int pos, int lim) { if(val > N) return ; f[num++] = node(pnum, val); LL nlim, nval, npnum; nval = val; nlim = 0; npnum = 1; while(nlim < lim && nval <= N) { nlim++; npnum++; nval *= prime[pos]; if(nval <= N) solve(npnum*pnum, nval, pos + 1, nlim); } } void get_antiprime() { get_prime(); num = 0; solve(1, 1, 0, 32); sort(f, f + num); } //---------上面全是打表------------------ int C[N], n; int lowbit(int i) {return i&(-i);} void Add(int p, int val) { while(p <= n) {C[p] += val; p += lowbit(p);} } int Sum(int p) { int res = 0; while(p > 0) { res += C[p]; p -= lowbit(p); } return res; } struct pnode { char name[20]; int x; } p[N]; int bs(int k) { int l = 1, r = n, mid, tmp; while(r - l >= 1) { mid = MID(l, r); tmp = Sum(mid); if(tmp >= k) r = mid; else l = mid + 1; } //printf("%d %d\n", l, r); return r; } int main() { //Read(); get_antiprime(); int k, i, g, mx; int now, cnt, nxt, nn, m; while(scanf("%d%d", &n, &k) != EOF) { CL(C, 0); for(i = 1; i <= n; ++i) { scanf("%s %d", p[i].name, &p[i].x); Add(i, 1); } mx = 0; g = 0; for(i = 0; i < num && f[i].b <= n; ++i) { if(f[i].a > mx) { mx = f[i].a; g = f[i].b; } } now = nxt = k; cnt = 1; while(cnt < g) { nn = n - cnt; m = p[now].x; if(m > 0) nxt = (nxt - 1 + m%nn)%nn; else nxt = ((nxt + m)%nn + nn)%nn; if(nxt == 0) nxt = nn; Add(now, -1); //printf("%d %s\n", now, p[now].name);; now = bs(nxt); //printf("%d %d %d\n", now, nxt, nn); cnt++; } printf("%s %d\n", p[now].name, mx); } return 0; }