poj 2886

线段树解决约瑟夫环问题,一开始要处理一下反质数

#include<iostream> using namespace std; #define MAXN 500002 struct Person{ char name[12]; int step; }person[MAXN]; int rprime[]={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,55440,83160,110880,166320,221760,277200,332640,498960}; int nprime[]={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}; int binarySearch(int target){ int low=0,high=34,mid; while(low<=high){ mid=(low+high)>>1; if(rprime[mid]==target) return mid; if(target>rprime[mid]) low=mid+1; else high=mid-1; } return high; } struct SegmentTree{ int left[MAXN*4],right[MAXN*4]; int sum[MAXN*4]; inline void build(int k,int l,int r){ left[k]=l; right[k]=r; sum[k]=1; if(l==r) return ; int m=(l+r)>>1; build(k*2,l,m); build(k*2+1,m+1,r); push_up(k); } inline void push_down(int k){ return ; } inline void push_up(int k){ if(left[k]!=right[k]) sum[k]=sum[k*2]+sum[k*2+1]; } inline int update(int k,int n){ if(left[k]==right[k]){ sum[k]=0; return left[k]; } else{ int tmp=sum[k*2]; int ret; if(tmp>=n) ret=update(k*2,n); else ret=update(k*2+1,n-tmp); push_up(k); return ret; } } inline void run(int m,int k){ int i; int total=sum[1]; k--; int ind; for(i=0;i<rprime[m];i++){ if(k<0) k=k+(-k)/total*total; k=(k+total)%total; k++; ind=update(1,k); total--; k=(k-1)+person[ind].step; if(person[ind].step>0) k--; } printf("%s %d/n",person[ind].name,nprime[m]); } }sgt; int main() { int n,k; while(scanf("%d%d",&n,&k)!=EOF){ int i; for(i=0;i<n;i++) scanf("%s%d",person[i].name,&person[i].step); int m=binarySearch(n); sgt.build(1,0,n-1); sgt.run(m,k); } }  

 

你可能感兴趣的:(struct,ini,Build,UP,360)