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
",query(1,now + 1));
42     }
43     return 0;
44 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj4415.html