poj2886Who Gets the Most Candies? (约瑟夫环)
http://poj.org/problem?id=2886
单点更新 初始位置都是1 如果这个人出去 位置变为0 利用线段树求区间k值 k值的计算如下
如果这个数值是负的 那么下一个人的就是((k-1+p[id].d)%n+n)%n+1; 如果是正的 下一个人就是(k-1+p[id].d-1)%n+1;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include<stdlib.h> 5 #include<iostream> 6 #include<cmath> 7 using namespace std; 8 #define N 500010 9 struct node 10 { 11 char s[12]; 12 int d; 13 }p[N]; 14 int s[N<<2],n,k,num,o[N],maxz,kk,key; 15 int a[37]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400, 16 55440,83160,110880,166320,221760,277200,332640,498960,500001}; 17 int b[37]={1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,80,84,90,96,100,108,120,128,144,160,168,180,192,200,1314521}; 18 void build(int l,int r,int w) 19 { 20 if(l==r) 21 { 22 s[w] = 1; 23 return ; 24 } 25 int m = (l+r)>>1; 26 build(l,m,w<<1); 27 build(m+1,r,w<<1|1); 28 s[w] = s[w<<1]+s[w<<1|1]; 29 } 30 void update(int p,int l,int r,int w) 31 { 32 if(l==r) 33 { 34 s[w] = 0; 35 key = l; 36 return ; 37 } 38 int m = (l+r)>>1; 39 if(p<=s[w<<1]) 40 update(p,l,m,w<<1); 41 else 42 update(p-s[w<<1],m+1,r,w<<1|1); 43 s[w] = s[w<<1] + s[w<<1|1]; 44 } 45 int main() 46 { 47 int i,j,sum; 48 while(scanf("%d%d",&n,&k)!=EOF) 49 { 50 kk=0;i=0;maxz=0; 51 while(a[i]<=n) i++; 52 kk = a[i-1]; 53 maxz = b[i-1]; 54 int nn = n; 55 build(1,n,1); 56 for(i = 1 ;i <= n ; i++) 57 scanf("%s%d",p[i].s,&p[i].d); 58 int id; 59 for(i = 0 ; i < kk ; i++) 60 { 61 n--; 62 update(k,1,nn,1); 63 id = key; 64 if(n==0) break; 65 if(p[id].d>0) 66 k = (k-1+p[id].d-1)%n+1; 67 else 68 k = ((k-1+p[id].d)%n+n)%n+1; 69 } 70 printf("%s %d\n",p[id].s,maxz); 71 } 72 }