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;
}
posted @ 2012-10-28 09:50  AC_Von  阅读(563)  评论(0编辑  收藏  举报