题目:http://poj.org/problem?id=2886
题意:有一群小朋友围成一个环,编号1,2,3…N。每个人手上握着一个非0的数字,首先第K个人出列,然后看他手上的数字,假设为m,则从下一个开始第m个人出列,一直如此。
第i个出列的人会得到 i的约数个数 个糖果,求得到最多糖果的人的名字和糖果数。
思路:先预处理每个数的约数个数,然后找出得到最多的糖果的是第几个出队的人,假设为res;
建立一个线段树,表示这一段还有几个人,
在更新时计算出出队的这个人的前面和后面的人的个数(L和R),用他手上的数字计算出是剩下人中的第几个人,然后进入线段树搜索出这个人的原始序号。。重复这个过程直到找到第res个出队的人,跳出循环
代码:

1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=500100; 7 struct node 8 { 9 char name[15]; 10 int num; 11 }st[maxn]; 12 int tree[maxn*4]; 13 int mark[maxn*4]; 14 int L,R; 15 int prim[maxn]; 16 void init() 17 { 18 int i,j; 19 memset(prim,0,sizeof(prim)); 20 for(i=1;i<=500000;i++) 21 { 22 for(j=i;j<=500000;j+=i) 23 { 24 prim[j]++; 25 } 26 } 27 } 28 void push(int w) 29 { 30 tree[w]=tree[w<<1]+tree[w<<1|1]; 31 } 32 void build(int l,int r,int w) 33 { 34 if(l==r) 35 { 36 tree[w]=1; 37 mark[w]=1; 38 return ; 39 } 40 int m=(l+r)>>1; 41 build(l,m,w<<1); 42 build(m+1,r,w<<1|1); 43 push(w); 44 } 45 void update(int now,int l,int r,int w) 46 { 47 tree[w]--; 48 if(l==r&&l==now) 49 { 50 return ; 51 } 52 int m=(l+r)/2; 53 if(now<=m) 54 { 55 R+=tree[w<<1|1]; 56 update(now,l,m,w<<1); 57 } 58 else 59 { 60 L+=tree[w<<1]; 61 update(now,m+1,r,w<<1|1); 62 } 63 } 64 int find(int x,int l,int r,int w) 65 { 66 while(l<=r) 67 { 68 if(mark[w]==1) 69 return l; 70 int m=(l+r)/2; 71 //printf("%d %d ",x,tree[w<<1]); 72 if(x<=tree[w<<1]) 73 { 74 r=m; 75 w=w<<1; 76 } 77 else 78 { 79 l=m+1; 80 x-=tree[w<<1]; 81 w=w<<1|1; 82 //printf("w=%d ",w); 83 84 } 85 86 //printf(" l=%d r=%d ",l,r); 87 } 88 } 89 int main() 90 { 91 int n,k; 92 init(); 93 while(scanf("%d%d",&n,&k)!=EOF) 94 { 95 int i; 96 for(i=1;i<=n;i++) 97 { 98 getchar(); 99 scanf("%s%d",st[i].name,&st[i].num); 100 } 101 int max=0; 102 int res=0; 103 for(i=1;i<=n;i++) 104 { 105 if(prim[i]>max) 106 { 107 max=prim[i]; 108 res=i; 109 } 110 111 } 112 //printf("res=%d ",res); 113 memset(mark,0,sizeof(mark)); 114 build(1,n,1); 115 int now=k; 116 for(i=1;i<=n;i++) 117 { 118 if(i==res) 119 break; 120 L=R=0; 121 update(now,1,n,1); 122 int u=st[now].num; 123 //printf("u=%d ",u); 124 //printf("L=%d R=%d ",L,R); 125 if(u<0) 126 { 127 u=-u; 128 u%=(L+R); 129 u=(L+R)-u+1; 130 } 131 if(u<R) 132 u=L+u; 133 else 134 u-=R,u%=(L+R); 135 if(u==0) 136 u=(L+R); 137 //printf("uu=%d ",u); 138 now=find(u,1,n,1); 139 //printf("now=%d ",now); 140 } 141 printf("%s %d ",st[now].name,prim[res]); 142 } 143 return 0; 144 }