POJ_2886 Who Gets the Most Candies? 二分+树状数组
Posted dybala21
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ_2886 Who Gets the Most Candies? 二分+树状数组相关的知识,希望对你有一定的参考价值。
一、题目
二、分析
这个题目吧,开始没读懂,做的时候也没懂,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 <cstdio> 2 #include <iostream> 3 #include <cstring> 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 ", Data[ID].s, Ans); 111 } 112 return 0; 113 }
以上是关于POJ_2886 Who Gets the Most Candies? 二分+树状数组的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2886Who Gets the Most Candies?
[poj 2886] Who Gets the Most Candies? 线段树
[POJ2886]Who Gets the Most Candies?
(线段树,反素数)poj2886-Who Gets the Most Candies?