N children are sitting in a circle to play a game.
The children are numbered from 1 to N in clockwise order. Each of them has a card with a non-zero integer on it in his/her hand. The game starts from the K-th child, who tells all the others the integer on his card and jumps out of the circle. The integer on his card tells the next child to jump out. Let A denote the integer. If A is positive, the next child will be the A-th child to the left. If A is negative, the next child will be the (−A)-th child to the right.
The game lasts until all children have jumped out of the circle. During the game, the p-th child jumping out will get F(p) candies where F(p) is the number of positive integers that perfectly divide p. Who gets the most candies?
4 2 Tom 2 Jack 4 Mary -1 Sam 1
Sam 3
建立线段树存放孩子在圈内的情况,每个叶节点表示一个孩子,如果叶节点i的值为1说明孩子i在圈内,为0则不在,那么问题每次我们让哪一位孩子出圈,就可以变成update哪个点的值,题目通过算出要离开圈的点在圈中是第几个,然后用线段树求出该点的下标
代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
#define M 500005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int tree[M<<2];
int f[M];
int n,k;
struct node{
char name[10];
int v;
}p[M];
void pushup(int rt)
{
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
tree[rt]=1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int update_query(int pos,int l,int r,int rt) //更新和查询
{
if(l==r)
{
tree[rt]=0;
return l; //l就是圈中第pos个孩子的下标
}
int m=(l+r)>>1;
int ret;
if(pos<=tree[rt<<1]) ret=update_query(pos,lson); //左子树有大于pos个孩子,则结果在左子树中
else ret=update_query(pos-tree[rt<<1],rson);
pushup(rt);
return ret;
}
void set_f() //求数的约数的个数
{
int i,j;
for(i=1;i<=500000;i++)
for(j=1;i*j<=500000;j++)
{
f[i*j]++;
}
}
int main()
{
int i;
set_f();
while(scanf("%d%d",&n,&k)!=EOF)
{
build(1,n,1);
for(i=1;i<=n;i++)
{
scanf("%s%d",p[i].name,&p[i].v);
}
if(n==1)
{
printf("%s 1\n",p[1].name);
continue;
}
int num=n; //num是圈中剩余人数
int ans=0;
char ans_name[10];
for(i=1;i<=n;i++)
{
int id=update_query(k,1,n,1); //k就是要出圈的孩子是圈中的第几个,id即是它的下标
num--;
int x=f[i]; //第i个出圈的人分到f[i]个糖果
int v=p[id].v; //用v来计算下一个k
if(ans<x) //注意不是<=,因为有多个结果输出先出圈的
{
ans=x;
strcpy(ans_name,p[id].name);
}
if(i==n) break;
int l=k-1; //刚出圈的孩子左边人数
int r=num-k+1; //右边人数
if(v>0)
{
v=v%num;
if(v==0) v=num;
if(r>=v) //下一个k在右边
k=l+v;
else //在左边
k=v-r;
}
else
{
v=(-v)%num;
if(v==0) v=num;
if(l>=v)
k=l-v+1;
else
k=l+r-(v-l)+1;
}
}
printf("%s %d\n",ans_name,ans);
}
return 0;
}