Play with Chain

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

【Problem Description】
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n. At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n. He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain. For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.
FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position. For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8
He wants to know what the chain looks like after perform m operations. Could you help him?
【Input】
There will be multiple test cases in a test data. For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively. Then m lines follow, each line contains one operation. The command is like this: CUT a b c   // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1). FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n. The input ends up with two negative numbers, which should not be processed as a case.
【Output】
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
【Sample Input】
8 2
CUT 3 5 4
FLIP 2 6
-1 -1

【Sample Output】

1 4 3 7 6 2 5 8

【题意】

给出一列数,然后对整个数列执行两种操作:切下一段插入到另外的位置,或者把其中的一整段整个翻转一下。

求经过一系列操作之后,数列最后的样子。

【分析】

数据范围最高能够到达3e5那么大,因此算法至少要是O(nlogn)复杂度以下才可能达到要求。

考虑采用Splay解决(这样的题目只能用这种动态维护的树结构不是么?)

初始先建树,把1~n加入Splay树。由于数列在后面是要被打乱顺序的,Splay二叉平衡树的性质只有在初始的时候是被保持的,之后是靠size,即每个点在中序遍历中的位置来维护。最后输出数列则只需要中序遍历一遍即可。

切割操作:若要切下a~b段,则把第a-1个结点移到根,把第b+1个结点移到根以下(即跟的右子树),则整个a~b段就落在b+1的左子树上,切出来。插入到c的时候,将c移到根,c+1移到根的右子树,则切出来的插入到c+1的左子树即可

翻转操作:用上面相同的方法把a~b整合到一棵子树上,然后可以参考线段树标记的方法,通过标记来完成访问结点的翻转等操作。

具体可以在纸上模拟一下......

【教训】

教训还是比较惨痛的...卡在这道题上好久了。

首先是输入输出以后要特别注意结尾方式,两个负数结尾还是两个-1结尾

把各种可能出现的不同情况考虑完整

  1 /* ***********************************************
  2 MYID    : Chen Fan
  3 LANG    : G++
  4 PROG    : HDU3487
  5 ************************************************ */
  6
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <algorithm>
 11
 12 using namespace std;
 13
 14 #define MAXN 300010
 15
 16 int sons[MAXN][2];
 17 int father[MAXN],size[MAXN],data[MAXN],list[MAXN];
 18 bool flag[MAXN];
 19 int spt=0,spttail=0;
 20
 21 void down(int x)
 22 {
 23     if (flag[x])
 24     {
 25         flag[x]=0;
 26         swap(sons[x][0],sons[x][1]);
 27         flag[sons[x][0]]^=1;
 28         flag[sons[x][1]]^=1;
 29     }
 30 }
 31
 32 void rotate(int x,int w) //rotate(node,0/1)
 33 {
 34     int y=father[x];
 35     down(y);down(x);
 36     sons[y][!w]=sons[x][w];
 37     if (sons[x][w]) father[sons[x][w]]=y;
 38
 39     father[x]=father[y];
 40     if (father[y]) sons[father[y]][y==sons[father[y]][1]]=x;
 41
 42     sons[x][w]=y;
 43     father[y]=x;
 44
 45     size[x]=size[y];
 46     size[y]=size[sons[y][0]]+size[sons[y][1]]+1;
 47 }
 48
 49 void splay(int x,int y) //splay(node,position)
 50 {
 51     down(x);
 52     while(father[x]!=y)
 53     {
 54         if (father[father[x]]==y) rotate(x,x==sons[father[x]][0]);
 55         else
 56         {
 57             int t=father[x];
 58             int w=(sons[father[t]][0]==t);
 59             if (sons[t][w]==x)
 60             {
 61                 rotate(x,!w);
 62                 rotate(x,w);
 63             } else
 64             {
 65                 rotate(t,w);
 66                 rotate(x,w);
 67             }
 68         }
 69     }
 70     if (!y) spt=x;
 71 }
 72
 73 void select(int x,int v,int p) //select(root,k,position)
 74 {
 75     down(x);
 76     while(v!=size[sons[x][0]]+1)
 77     {
 78         if (v<=size[sons[x][0]])
 79         {
 80             x=sons[x][0];
 81             down(x);
 82         }
 83         else
 84         {
 85             v-=size[sons[x][0]]+1;
 86             x=sons[x][1];
 87             down(x);
 88         }
 89     }
 90     splay(x,p);
 91 }
 92
 93 bool done=false;
 94
 95 void outp(int x)
 96 {
 97     down(x);
 98     if (sons[x][0]) outp(sons[x][0]);
 99     if (done) printf(" ");
100     done=true;
101     printf("%d",data[x]);
102     if (sons[x][1]) outp(sons[x][1]);
103 }
104
105 void maketree(int l,int r)
106 {
107     spttail++;
108     int now=spttail,w=(l+r)/2,ls=0,rs=0;
109     data[now]=w;
110     flag[now]=false;
111     sons[now][0]=0;
112     sons[now][1]=0;
113
114     if (l<=w-1)
115     {
116         ls=spttail+1;
117         sons[now][0]=ls;
118         father[ls]=now;
119         maketree(l,w-1);
120     }
121     if (w+1<=r)
122     {
123         rs=spttail+1;
124         sons[now][1]=rs;
125         father[rs]=now;
126         maketree(w+1,r);
127     }
128
129     size[now]=size[ls]+size[rs]+1;
130 }
131
132 int main()
133 {
134     freopen("3487.txt","r",stdin);
135
136     int n,m;
137     scanf("%d%d",&n,&m);
138     while(!(n<0&&m<0))
139     {
140         spt=1;
141         spttail=0;
142         father[1]=0;
143         maketree(1,n);
144
145         for (int i=1;i<=m;i++)
146         {
147             char s[10];
148             scanf("%s",&s);
149             if (s[0]=='C')
150             {
151                 int a,b,c,temp;
152                 scanf("%d%d%d",&a,&b,&c);
153
154                 if (a>1)
155                 {
156                     select(spt,a-1,0);
157                     if (b<n)
158                     {
159                         select(spt,b+1,spt);
160                         temp=sons[sons[spt][1]][0];
161                         sons[sons[spt][1]][0]=0;
162                         size[spt]-=size[temp];
163                         size[sons[spt][1]]-=size[temp];
164                     } else
165                     {
166                         temp=sons[spt][1];
167                         sons[spt][1]=0;
168                         size[spt]-=size[temp];
169                     }
170                 } else
171                 {
172                     if (b<n)
173                     {
174                         select(spt,b+1,0);
175                         temp=sons[spt][0];
176                         sons[spt][0]=0;
177                         size[spt]-=size[temp];
178                     } else temp=spt;
179                 }
180
181                 if (c>0)
182                 {
183                     select(spt,c,0);
184                     if (c==size[spt])
185                     {
186                         sons[spt][1]=temp;
187                         father[temp]=spt;
188                         size[spt]+=size[temp];
189                     } else
190                     {
191                         select(spt,c+1,spt);
192                         sons[sons[spt][1]][0]=temp;
193                         father[temp]=sons[spt][1];
194                         size[spt]+=size[temp];
195                         size[sons[spt][1]]+=size[temp];
196                     }
197                 } else
198                 {
199                     if (spt!=temp)
200                     {
201                         select(spt,1,0);
202                         sons[spt][0]=temp;
203                         father[temp]=spt;
204                         size[spt]+=size[temp];
205                     }
206                 }
207             } else
208             {
209                 int a,b,temp;
210                 scanf("%d%d",&a,&b);
211                 if (a>1)
212                 {
213                     select(spt,a-1,0);
214                     if (b<n)
215                     {
216                         select(spt,b+1,spt);
217                         temp=sons[sons[spt][1]][0];
218                     } else
219                     {
220                         temp=sons[spt][1];
221                     }
222                 } else
223                 {
224                     if (b<n)
225                     {
226                         select(spt,b+1,0);
227                         temp=sons[spt][0];
228                     } else temp=spt;
229                 }
230                 flag[temp]^=1;
231             }
232         }
233         done=false;
234         outp(spt);
235         printf("\n");
236         scanf("%d%d",&n,&m);
237     }
238
239     return 0;
240 }

View Code

转载于:https://www.cnblogs.com/jcf94/p/4374315.html

HDU 3487 Play with Chain | Splay相关推荐

  1. HDU 3487 Play with Chain(Splay)

    题目大意 给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作 操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数 ...

  2. 【HDOJ】3487 Play with Chain

    Splay入门题目,区间翻转,区间分割. 1 /* */ 2 #include <iostream> 3 #include <string> 4 #include <ma ...

  3. ●HDU 2871 Memory Control(Splay)

    ●赘述题目 四种操作: ○Reset:将整个内存序列清空. ○New a:在尽量靠左的位置新建一个长度为a的内存块,并输出改内存块起始位置.(各个内存块即使相邻也不会合并..) ○Free a:将a点 ...

  4. 【HDU】6072 Logic Chain - kosaraju+bitset

    题解 貌似此题只能用kosaraju+bitset压位搞过去? 设每次修改后的图中强连通分量有 n n n个,第 i i i个scc的点数为 p i p_i pi​, 那么答案就是: ∑ i = 1 ...

  5. confluence添加用户_Confluence 6 选项 1 – 在 Confluence 中手动重建用户和用户组

    dojo 六 使用query dojo/query 要使用query,就要引入dojo/query包.query可以根据Dom里节点的标签名.id名.class名来检索一个或多个节点.-------- ...

  6. [kuangbin]各种各样的题单

    [kuangbin]各种各样的题单 专题1 简单搜索 POJ 1321 POJ 2251 POJ 3278 POJ 3279 POJ 1426 POJ 3126 POJ 3087 POJ 3414 F ...

  7. 【博弈论】博弈论题单题解

    会不断更新的(咕咕咕) 题目难度大致满足非降性 博弈论真是深坑啊,填不动了,还有Nim积.Every-SG游戏等等等等很多题型还不会,先去学别的了 涉及知识: SG函数及SG定理:传送门 博弈论知识总 ...

  8. RADOS分布式对象存储原理简介

    Ceph是一个开源的PB级文件系统,最早是加州大学Santa Cruz分校的一个研究项目,项目创始人sage weil是该校的一名博士.ceph包括一个兼容POSIX的分布式文件CephFS,一个分布 ...

  9. 【splay】hdu 4453 2012杭州赛区A题

    http://acm.hdu.edu.cn/showproblem.php?pid=4453 普通的splay,但是出题人很无聊的给题目加上了很多限制,使得双向链表也可以处理,但是我还是比较喜欢spl ...

最新文章

  1. 写python程序用什么软件最好-Python必学之编译器用哪个好?你用错了吧!
  2. oracle触发器的类型及使用方法
  3. 从工作的角度,NLP/CV/推荐系统选哪个?
  4. 分享字符串右移的算法
  5. 莫侵残日噪,正在异乡听
  6. ChildWindow在Open时旋转出现
  7. python Web开发你要理解的WSGI uwsgi详解
  8. 一套简单的进销存管理系统源码
  9. vue中播放消息提示音
  10. 极简 Java 工作流概念入门
  11. Win10怎样关闭自动维护
  12. 互动媒体技术作业——processing码绘
  13. 02-gitgitlab二次认证
  14. Python快速上手系列--循环结构--基础篇
  15. 开发im即时通讯如何用Netty实现心跳机制、断线重连机制
  16. 【干货】五个免费下载PPT模板的网站,你一定会用到的
  17. python pdf 数据转excel 表格_python实现PDF中表格转化为Excel的方法
  18. 怎么识别截图中的文字?这三个方法让你轻松学会
  19. python计算上证50ETF的已实现波动率
  20. 游戏设计自学记录(19)

热门文章

  1. android navigation bar高度,Android获取屏幕真实高度包含NavigationBar(底部虚拟按键)
  2. 电脑技巧:C盘爆满该如何清理,实用的清理方案,小白必备
  3. 2019 Vue开发指南:你都需要学点啥?
  4. mysql009模糊查询like.是否为null
  5. windows挂载linux网络文件系统NFS
  6. 模态和非模态代码_我们如何使模态可用和可访问?
  7. 一道很熟悉的前端面试题,你怎么答?
  8. 解决npm 的 shasum check failed for错误
  9. Gradle 1.12用户指南翻译——第五十四章. 构建原生二进制文件
  10. Servlet 应用程序事件、监听器