【SHOI2013】【BZOJ4415】发牌

Description

假设一开始,荷官拿出了一副新牌,这副牌有N张不同的牌,编号依次为1到N。由于是新牌,所以牌是按照顺序排好的,从牌库顶开始,依次为1, 2,……直到N,N号牌在牌库底。为了发完所有的牌,荷官会进行N次发牌操作,在第i次发牌之前,他会连续进行R_i次销牌操作,R_i由输入给定。请问最后玩家拿到这副牌的顺序是什么样的?

举个例子,假设N = 4,则一开始的时候,牌库中牌的构成顺序为{1, 2, 3, 4}。

假设R1=2,则荷官应该连销两次牌,将1和2放入牌库底,再将3发给玩家。目前牌库中的牌顺序为{4, 1, 2}。

假设R2=0,荷官不需要销牌,直接将4发给玩家,目前牌库中的牌顺序为{1,2}。

假设R3=3,则荷官依次销去了1, 2, 1,再将2发给了玩家。目前牌库仅剩下一张牌1。

假设R4=2,荷官在重复销去两次1之后,还是将1发给了玩家,这是因为1是牌库中唯一的一张牌。

Input

第1行,一个整数N,表示牌的数量。第2行到第N + 1行,在第i + 1行,有一个整数R_i, 0≤R_i

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define lchild rt<<1,l,mid
#define rchild rt<<1|1,mid+1,r
#define ln rt<<1
#define rn rt<<1|1
#define MAXN 700010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,x;
struct seg
{
    int l,r,msg;
}tree[MAXN*3];
void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
void build(int rt=1,int l=1,int r=n)
{
    tree[rt].l=l;tree[rt].r=r;
    if (l==r)   {   tree[rt].msg=1;return;  }
    int mid=(l+r)>>1;build(lchild);build(rchild);tree[rt].msg=r-l+1;
}
int query(int rt,int x)
{
    int L=tree[rt].l,R=tree[rt].r;
    tree[rt].msg--;return L==R?L:(tree[ln].msg>=x?query(ln,x):query(rn,x-tree[ln].msg));
}
int main()
{
    in(n);build();int now=0;
    while (n--) in(x),(now+=x)%=(n+1),printf("%d\n",query(1,now+1));
}

你可能感兴趣的:(线段树)