模拟约瑟夫环
转化成求动态数据的第k值,然后就可以用树状数组加二分的办法来处理。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=5e5+9;
int ans[maxn],tr[maxn];
char name[maxn][15];
int a[maxn];
int cnt[maxn];
bool is[maxn];
int n,k;
void add(int x,int tmp)
{
for(int i=x;i<=n;i+=(i&-i))
tr[i]+=tmp;
}
int getsum(int x)
{
int ret=0;
for(int i=x;i>=1;i-=(i&-i))
ret+=tr[i];
return ret;
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&k)!=EOF)
{
memset(is,0,sizeof(is));
memset(tr,0,sizeof(tr));
for(int i=1;i<=n;i++)
add(i,1);
add(k,-1);
ans[1]=k;
is[k]=1;
for(int i=1;i<=n;i++)
{
scanf("%s",&name[i][1]);
scanf("%d",&a[i]);
}
// cout<<a[2]<<endl;
for(int i=2,tmp=k;i<=n;i++)
{
if(a[tmp]>0)
{
a[tmp]+=getsum(tmp);
a[tmp]%=(n-i+1);
if(a[tmp]==0) a[tmp]=n-i+1;
int st=1,ed=n,mid;
while(st<ed)
{
mid=st+ed>>1;
if(getsum(mid)<a[tmp]) st=mid+1;
else ed=mid;
}
add(st,-1);
ans[i]=st;
tmp=st;
is[st]=1;
}
else
{
a[tmp]=-a[tmp];
a[tmp]+=(n-i+1-getsum(tmp)+!is[tmp]);
a[tmp]%=(n-i+1);
if(a[tmp]==0) a[tmp]=n-i+1;
int st=1,ed=n,mid;
while(st<ed)
{
mid=st+ed>>1;
if(n-i+1-getsum(mid)<a[tmp]) ed=mid;
else st=mid+1;
}
add(st,-1);
ans[i]=st;
tmp=st;
is[st]=1;
}
}
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j+=i)
{
cnt[j]++;
}
int sum=0,tmp;
for(int i=1;i<=n;i++)
if(cnt[i]>sum)
{
sum=cnt[i];
tmp=i;
}
printf("%s %d\n",&name[ans[tmp]][1],sum);
}
return 0;
}