BZOJ4415 [SHOI2013] 发牌
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4415
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<N
Output
第1行到第N行:第i行只有一个整数,表示玩家收到的第i张牌的编号。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 using namespace std; 8 const int maxn = 700010; 9 inline int read(){ 10 int ans = 0, f = 1; 11 char c = getchar(); 12 for(; !isdigit(c); c = getchar()) 13 if (c == '-') f = -1; 14 for(; isdigit(c); c = getchar()) 15 ans = ans * 10 + c - '0'; 16 return ans * f; 17 } 18 struct Node{ 19 int l,r,s; 20 }t[maxn<<2]; 21 void build(int u,int v,int w){ 22 t[w].l = u; t[w].r = v; 23 if (u == v){ 24 t[w].s = 1; return; 25 } 26 int mid = (u + v) >> 1; 27 build(u,mid,w<<1); build(mid+1,v,w<<1|1); 28 t[w].s = v - u + 1; 29 } 30 int query(int w,int x){ 31 t[w].s--; 32 if (t[w].l == t[w].r) return t[w].l; 33 if (t[w<<1].s >= x) return query(w<<1,x); 34 else return query(w<<1|1,x-t[w<<1].s); 35 } 36 int main(){ 37 int n = read(); int now = 0; 38 build(1,n,1); 39 rep(i,1,n){ 40 int x = read(); now = (now + x) % (n - i + 1); 41 printf("%d\n",query(1,now + 1)); 42 } 43 return 0; 44 }