poj 2886 Who Gets the Most Candies?(线段树单点更新)

题目: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\n",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\n",w);
 83 
 84         }
 85 
 86         //printf("\nl=%d r=%d\n",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\n",now);
140         }
141         printf("%s %d\n",st[now].name,prim[res]);
142     }
143     return 0;
144 }
View Code

 

  

 

posted @ 2013-06-18 22:04  琳&leen  阅读(212)  评论(0编辑  收藏  举报