POJ_2886 Who Gets the Most Candies? 【二分+树状数组】

一、题目

POJ2886

二、分析

  这个题目吧,开始没读懂,做的时候也没懂,WA的时候懂了。假设是第p个出圈的人有一个对应的因子个数$F(p)$,那么,题目求的就是这个$F(p)$最大的对应的人。

  1.首先要对所有$F(p)$值进行预处理打表。因为多次询问。

  2.每次都会有一个人出圈,那么为了能够每次方便的查到(新圈)第K个人的下标,需要对出圈的人进行处理,这里可以用树状数组,表示第pos个位置前还有多少个人在,如果不在,就对树状数组进行维护。需要注意的是树状数组需要初始化,即开始的时候每个人都是在自己的位置上的。

  3.确定K,确定K的时候,思路比较绕,画个图就明白了。总结一下,就是对于当前位置pos,对应的是当前圈的第K个人,那么下一时刻,他就出圈了。

  如果是他手里的数字是正,那么相当于从旧圈的第K-1个人开始考虑。

  如果手里的数字是负,因为新圈里,第K个人的位置被前一个圈的 K + 1个人顶替了,所以不用管。

  然后取余就可以了,注意细节就行。

  4.第K个人确定了,那么就需要找了,利用BIT的求和直接二分找就可以了。这里要注意找的是$F(p)$最大值对应的人。(最开始就是没注意这个WA了好多次)

三、AC代码

  1 #include 
  2 #include 
  3 #include 
  4 
  5 using namespace std;
  6 
  7 const int MAXN = 5e5 + 100;
  8 
  9 struct Node
 10 {
 11     char s[15];
 12     int num;
 13 }Data[MAXN];
 14 
 15 int BIT[MAXN];
 16 int Prime[MAXN] = {0};
 17 int N, K, Ans, ID;
 18 
 19 void getPrime()
 20 {
 21     for(int i = 1; i < MAXN; i++)
 22     {
 23         for(int j = i; j < MAXN; j += i)
 24         {
 25             Prime[j]++;
 26         }
 27     }
 28 }
 29 
 30 void add(int x, int v)
 31 {
 32     while(x <= MAXN)
 33     {
 34         BIT[x] += v;
 35         x += x & -x;
 36     }
 37 }
 38 
 39 int sum(int x)
 40 {
 41     int ans = 0;
 42     while(x)
 43     {
 44         ans += BIT[x];
 45         x -= x & -x;
 46     }
 47     return ans;
 48 }
 49 
 50 int getPos(int t)
 51 {
 52     int left = 0, right = N, mid;
 53     while(left + 1 < right)
 54     {
 55         mid = (left + right) >> 1;
 56         if(sum(mid) < t)
 57             left = mid;
 58         else
 59             right = mid;
 60     }
 61     return right;
 62 }
 63 
 64 void solve()
 65 {
 66     int pos, temp;
 67     for(int i = N - 1; i > 0; i--)
 68     {
 69         pos = getPos(K);
 70         add(pos, -1);
 71         temp = Prime[N - i];
 72         if(Ans < temp)
 73         {
 74             Ans = temp;
 75             ID = pos;
 76         }
 77         if(Data[pos].num > 0)
 78         {
 79             K--;
 80         }
 81         K += Data[pos].num;
 82         K = (K%i + i) % i;
 83         if(K == 0)
 84             K = i;
 85     }
 86     K = getPos(K);
 87     temp = Prime[N];
 88     if(Ans < temp)
 89     {
 90         Ans = temp;
 91         ID = K;
 92     }
 93         
 94 }
 95 
 96 int main()
 97 {
 98     //freopen("input.txt", "r", stdin);
 99     getPrime();
100     while(scanf("%d %d", &N, &K) != EOF)
101     {
102         memset(BIT, 0, sizeof(BIT));
103         for(int i = 1; i <= N; i++)
104         {
105             add(i, 1);
106             scanf("%s %d", Data[i].s, &Data[i].num);
107         }
108         Ans = 0;
109         solve();
110         printf("%s %d\n", Data[ID].s, Ans);
111     }
112     return 0;
113 }

 

转载于:https://www.cnblogs.com/dybala21/p/10536771.html

你可能感兴趣的:(POJ_2886 Who Gets the Most Candies? 【二分+树状数组】)