博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4415:[SHOI2013]发牌(线段树)
阅读量:7023 次
发布时间:2019-06-28

本文共 3980 字,大约阅读时间需要 13 分钟。

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张牌的编号。

Sample Input

4
2
0
3
2

Sample Output

3
4
2
1

HINT

N<=70万

Solution

一看是splay裸题就上splay硬艹结果因为人傻常数大只有80……于是换了线段树写法

开个线段树存一下每种牌的数量0/1

在值域线段树上二分即可。
代码简单易懂

最后面贴一下我GG的splay

Code

1 #include
2 #include
3 #define N (700000+1000) 4 using namespace std; 5 6 int Segt[N<<2]; 7 8 inline int read() 9 {10 int x=0,w=1; char c=getchar();11 while (!isdigit(c)&&c!='-') c=getchar();12 if (c=='-') c=getchar(),w=-1;13 while (isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}14 return x*w;15 }16 17 void Build(int now,int l,int r)18 {19 if (l==r){Segt[now]=1; return;}20 int mid=(l+r)>>1;21 Build(now<<1,l,mid); Build(now<<1|1,mid+1,r);22 Segt[now]=Segt[now<<1]+Segt[now<<1|1];23 }24 25 void Update(int now,int l,int r,int k)26 {27 Segt[now]--;28 if (l==r){printf("%d\n",l); return;}29 int mid=(l+r)>>1;30 if (k<=Segt[now<<1]) Update(now<<1,l,mid,k);31 else Update(now<<1|1,mid+1,r,k-Segt[now<<1]);32 }33 34 int main()35 {36 int n,x,p=0;37 n=read();38 Build(1,1,n);39 for (int i=1; i<=n; ++i)40 {41 x=read();42 p=(p+x)%(n-i+1);43 Update(1,1,n,p+1);44 }45 }

 

1 #include
2 #include
3 #define N (700000+1000) 4 using namespace std; 5 6 int n,x,Root,Father[N],Son[N][2],Size[N]; 7 8 void Update(int x){Size[x]=1+Size[Son[x][0]]+Size[Son[x][1]];} 9 int Get(int x){
return Son[Father[x]][1]==x;}10 11 inline int read()12 {13 int x=0,w=1;14 char c=getchar();15 while (!isdigit(c)&&c!='-') c=getchar();16 if (c=='-') c=getchar(),w=-1;17 while (isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}18 return x*w;19 }20 21 void Build(int fa,int l,int r)22 {23 if (l>r) return;24 if (l==r) Size[l]=1;25 int mid=(l+r)>>1;26 Build(mid,l,mid-1);27 Build(mid,mid+1,r);28 Father[mid]=fa; Son[fa][mid>fa]=mid;29 Update(mid);30 }31 32 void Rotate(int x)33 {34 int wh=Get(x);35 int fa=Father[x],fafa=Father[fa];36 if (fafa) Son[fafa][Son[fafa][1]==fa]=x;37 Father[fa]=x; Son[fa][wh]=Son[x][wh^1];38 Father[x]=fafa; Son[x][wh^1]=fa;39 if (Son[fa][wh]) Father[Son[fa][wh]]=fa;40 Update(fa); Update(x);41 }42 43 void Splay(int x,int tar)44 {45 for (int fa; (fa=Father[x])!=tar; Rotate(x))46 if (Father[fa]!=tar)47 Rotate(Get(fa)==Get(x)?fa:x);48 if (!tar) Root=x;49 }50 51 int Findkth(int x)52 {53 int now=Root;54 while (1)55 if (Size[Son[now][0]]>=x) now=Son[now][0];56 else57 {58 x-=Size[Son[now][0]];59 if (x==1){
/*Splay(now,0);*/ return now;}60 x--; now=Son[now][1];61 }62 }63 64 int Split(int l,int r)65 {66 int x=Findkth(l);67 int y=Findkth(r+2);68 Splay(x,0); Splay(y,x);69 return Son[y][0];70 }71 72 int main()73 {74 n=read();75 Build(0,1,n+2);76 Root=(n+3)>>1;77 for (int i=1; i<=n; ++i)78 {79 x=read();80 x%=n-i+1;81 if (x)82 {83 int now=Split(1,x);84 Son[Father[now]][Son[Father[now]][1]==now]=0;85 Father[now]=0;86 int fa=Split(n-i+1-x,n-i+1-x);87 Son[fa][1]=now; Father[now]=fa;88 Splay(now,0);89 }90 int now=Split(1,1); printf("%d\n",now-1);91 Son[Father[now]][0]=0;92 Father[now]=0; Update(Son[Root][1]);93 }94 }

转载于:https://www.cnblogs.com/refun/p/9236055.html

你可能感兴趣的文章
OSChina 周日乱弹 ——程序员女友爆照!404
查看>>
swift3.0 dispatch_after 延时操作
查看>>
NGUI v301 官网详解 Example 3 - Menu
查看>>
抽象工厂模式——创建型模式
查看>>
网页检测摇一摇
查看>>
2013-9-11
查看>>
使用 Jersey 和 Apache Tomcat 7 构建 JAX-RS 环境
查看>>
正则的部分表达式(转载)
查看>>
hql查询
查看>>
模仿酷狗7(Kugou7)音乐魔方界面源码
查看>>
剑指offer之字符串是否为数值
查看>>
我的友情链接
查看>>
HTTP Cookie 详解
查看>>
Lab4-CUCM PUB First Configuration
查看>>
关于MS12-020 3389 0day exp 远程桌面执行代码漏洞的文章
查看>>
既然入了IT这行得不停的学习,不进则退
查看>>
本地项目上传到github
查看>>
调试Angular代码的Batarang插件不能用的问题
查看>>
文件测试
查看>>
Java指定网页打开Chrome浏览器
查看>>