Poj--2886(线段树 or 树状数组,二分,反素数)
2014-10-01 15:31:32
思路:这题调了我N久,二分的基础还是弱QAQ。我的方法是:用首先用树状数组来维护出入队的情况,初始1-N都是1,第k个人出队,则k的位置减一。在找下一个人的位置的时候用二分,注意:二分查到的位置不能是已经出队的人!借鉴了别人优雅的反素数求法。~~~~
1 /************************************************************************* 2 > File Name: 2886.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 30 Sep 2014 09:32:25 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 #define lpos (pos << 1) 18 #define rpos (pos << 1|1) 19 #define getmid(l,r) (l + (r - l) / 2) 20 typedef long long ll; 21 const int INF = 1 << 30; 22 const int maxn = 500010; 23 24 int ans,ansn,N,K; 25 char name[maxn][15]; 26 int c[maxn],card[maxn]; 27 int fnum[maxn],atp[maxn]; 28 29 int Lowbit(int x){ return x & (-x);} 30 void Update(int x,int d){while(x <= N){ c[x] += d,x += Lowbit(x);}} 31 int Getsum(int x){int res = 0;while(x){ res += c[x],x -= Lowbit(x);} return res;} 32 33 void Pre(){ 34 memset(fnum,0,sizeof(fnum)); 35 for(int i = 1; i <= maxn; ++i) 36 for(int j = i; j <= maxn; j += i) 37 ++fnum[j]; 38 ansn = 0; 39 for(int i = 1; i <= N; ++i){ 40 if(fnum[i] > ansn){ 41 ans = i; 42 ansn = fnum[i]; 43 } 44 } 45 } 46 47 int B_search(int k){ 48 int l = 1,r = N,mid,tmp; 49 while(l < r){ 50 mid = getmid(l,r); 51 tmp = Getsum(mid); 52 if(tmp < k) l = mid + 1; 53 else r = mid; 54 } 55 return l; 56 } 57 58 int main(){ 59 scanf("%d%d",&N,&K); 60 Pre(); 61 for(int i = 1; i <= N; ++i){ 62 scanf("%s%d",name[i],&card[i]); 63 Update(i,1); 64 } 65 int pos = K,sum = N,next,ln,rn,cnt = 0; 66 while(cnt < ans - 1){ 67 Update(pos,-1); 68 --sum; 69 ln = Getsum(pos); 70 rn = sum - ln; 71 if(card[pos] > 0){ 72 card[pos] %= sum; 73 if(card[pos] == 0) card[pos] = sum; 74 if(card[pos] <= rn) 75 next = B_search(ln + card[pos]); 76 else 77 next = B_search(card[pos] - rn); 78 } 79 else{ 80 card[pos] = -card[pos]; 81 card[pos] %= sum; 82 if(card[pos] == 0) card[pos] = sum; 83 if(card[pos] <= ln) 84 next = B_search(ln - card[pos] + 1); 85 else 86 next = B_search(sum - (card[pos] - ln) + 1); 87 } 88 pos = next; 89 cnt++; 90 } 91 printf("%s %d\n",name[pos],ansn); 92 return 0; 93 }