/*到1号节点的距离为s的点,则该点的相对节点1的编号为(s+n)%n+1,另外此题要打表求某个数的因子个数
反素数就是 对 x来说约束个数 G(x),如果 对于 i<x 有 G(i)<G(x)
则称x为反素数*/
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=500002;
//反素数及因子个数打表
int ap[40] ={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,500001};
int num[40]={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};
char s[maxn][15];
int val[maxn];
int tree[maxn<<2]; //维护区间人数
void Pushup(int p)
{
tree[p]=tree[p<<1]+tree[p<<1|1];
}
void Build(int p,int l,int r)
{
if(l==r){ tree[p]=1; return; }
int mid=(l+r)/2;
Build(p<<1,l,mid);
Build(p<<1|1,mid+1,r);
Pushup(p);
}
int Update(int p,int l,int r,int k)
{
if(l==r){ tree[p]=0; return l; }
int mid=(l+r)/2;
int ret;
if(k<=tree[p<<1]) ret= Update(p<<1,l,mid,k);
else ret= Update(p<<1|1,mid+1,r,k-tree[p<<1]);
Pushup(p);
return ret;
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%s %d",s[i],&val[i]);
Build(1,1,n);
int t,pos,tt;
for(int i=0;ap[i]<=n;i++) t=i;
tt=ap[t]; //出队次序
pos=num[t]; //最多的因子个数
int m=n;
int i;
i=Update(1,1,n,k);
int ans=1;
while(m--)
{
int mod=m; //当前的未出队的人数
if(val[i]>0)
k=((k+val[i]-1-1)%mod+mod)%mod+1; //下一个出队的人的相对1号节点的新的编号
else k=((k+val[i]-1)%mod+mod)%mod+1;
i=Update(1,1,n,k); //删除的队员实际编号
// cout<<k<<' '<<i<<endl;
ans++;
if(ans==tt) break;
}
cout<<s[i]<<' '<<pos<<endl;
}
return 0;
}
poj2886(线段树单点更新)
最新推荐文章于 2019-04-29 13:17:00 发布