zoukankan      html  css  js  c++  java
  • POJ 2886 Who Gets the Most Candies?

    POJ_2886

        由于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;
    }


  • 相关阅读:
    sourceinsight问题
    mysql函数调用过程
    visual studio 中sstrcpy报错的问题
    mysql基本操作
    c/c++程序连接mysql
    mysql 在visual studio中的配置
    va_start
    c do{}while(0)
    .NET 通用权限设计
    https://zhidao.baidu.com/question/362784520674844572.html
  • 原文地址:https://www.cnblogs.com/staginner/p/2433952.html
Copyright © 2011-2022 走看看