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】
  1. CUT
  2. FLIP
  3. - -

【Sample Output】

【题意】

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

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

【分析】

数据范围最高能够到达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][];
  17. int father[MAXN],size[MAXN],data[MAXN],list[MAXN];
  18. bool flag[MAXN];
  19. int spt=,spttail=;
  20.  
  21. void down(int x)
  22. {
  23. if (flag[x])
  24. {
  25. flag[x]=;
  26. swap(sons[x][],sons[x][]);
  27. flag[sons[x][]]^=;
  28. flag[sons[x][]]^=;
  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]][]]=x;
  41.  
  42. sons[x][w]=y;
  43. father[y]=x;
  44.  
  45. size[x]=size[y];
  46. size[y]=size[sons[y][]]+size[sons[y][]]+;
  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]][]);
  55. else
  56. {
  57. int t=father[x];
  58. int w=(sons[father[t]][]==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][]]+)
  77. {
  78. if (v<=size[sons[x][]])
  79. {
  80. x=sons[x][];
  81. down(x);
  82. }
  83. else
  84. {
  85. v-=size[sons[x][]]+;
  86. x=sons[x][];
  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][]) outp(sons[x][]);
  99. if (done) printf(" ");
  100. done=true;
  101. printf("%d",data[x]);
  102. if (sons[x][]) outp(sons[x][]);
  103. }
  104.  
  105. void maketree(int l,int r)
  106. {
  107. spttail++;
  108. int now=spttail,w=(l+r)/,ls=,rs=;
  109. data[now]=w;
  110. flag[now]=false;
  111. sons[now][]=;
  112. sons[now][]=;
  113.  
  114. if (l<=w-)
  115. {
  116. ls=spttail+;
  117. sons[now][]=ls;
  118. father[ls]=now;
  119. maketree(l,w-);
  120. }
  121. if (w+<=r)
  122. {
  123. rs=spttail+;
  124. sons[now][]=rs;
  125. father[rs]=now;
  126. maketree(w+,r);
  127. }
  128.  
  129. size[now]=size[ls]+size[rs]+;
  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<&&m<))
  139. {
  140. spt=;
  141. spttail=;
  142. father[]=;
  143. maketree(,n);
  144.  
  145. for (int i=;i<=m;i++)
  146. {
  147. char s[];
  148. scanf("%s",&s);
  149. if (s[]=='C')
  150. {
  151. int a,b,c,temp;
  152. scanf("%d%d%d",&a,&b,&c);
  153.  
  154. if (a>)
  155. {
  156. select(spt,a-,);
  157. if (b<n)
  158. {
  159. select(spt,b+,spt);
  160. temp=sons[sons[spt][]][];
  161. sons[sons[spt][]][]=;
  162. size[spt]-=size[temp];
  163. size[sons[spt][]]-=size[temp];
  164. } else
  165. {
  166. temp=sons[spt][];
  167. sons[spt][]=;
  168. size[spt]-=size[temp];
  169. }
  170. } else
  171. {
  172. if (b<n)
  173. {
  174. select(spt,b+,);
  175. temp=sons[spt][];
  176. sons[spt][]=;
  177. size[spt]-=size[temp];
  178. } else temp=spt;
  179. }
  180.  
  181. if (c>)
  182. {
  183. select(spt,c,);
  184. if (c==size[spt])
  185. {
  186. sons[spt][]=temp;
  187. father[temp]=spt;
  188. size[spt]+=size[temp];
  189. } else
  190. {
  191. select(spt,c+,spt);
  192. sons[sons[spt][]][]=temp;
  193. father[temp]=sons[spt][];
  194. size[spt]+=size[temp];
  195. size[sons[spt][]]+=size[temp];
  196. }
  197. } else
  198. {
  199. if (spt!=temp)
  200. {
  201. select(spt,,);
  202. sons[spt][]=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>)
  212. {
  213. select(spt,a-,);
  214. if (b<n)
  215. {
  216. select(spt,b+,spt);
  217. temp=sons[sons[spt][]][];
  218. } else
  219. {
  220. temp=sons[spt][];
  221. }
  222. } else
  223. {
  224. if (b<n)
  225. {
  226. select(spt,b+,);
  227. temp=sons[spt][];
  228. } else temp=spt;
  229. }
  230. flag[temp]^=;
  231. }
  232. }
  233. done=false;
  234. outp(spt);
  235. printf("\n");
  236. scanf("%d%d",&n,&m);
  237. }
  238.  
  239. return ;
  240. }

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. hdu 3487 Play with Chain

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a c ...

  3. HDU 3487 Play with Chain (splay tree)

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  4. HDU 3487 Play with Chain 【Splay】

    1-n的序列,有两种操作: 1,将一段区间翻转 2,将一段区间切下来放到剩余序列的第C个数后 采用延迟更新的方法维护区间的翻转,并维护一个size域. 添加一个最大点和一个最小点,防止出界 翻转时,将 ...

  5. Hdu 3487 play the chain

    Description 瑶瑶很喜欢玩项链,她有一根项链上面有很多宝石,宝石从1到n编号. 首先,项链上的宝石的编号组成一个序列:1,2,3,...,n. 她喜欢两种操作: 1.CUT a b c:他会 ...

  6. HDU 3487:Play with Chain(Splay)

    http://acm.hdu.edu.cn/showproblem.php?pid=3487 题意:有两种操作:1.Flip l r ,把 l 到 r 这段区间 reverse.2.Cut a b c ...

  7. 【HDU 3487】Play with Chain Splay

    题意 给定$n$个数序列,每次两个操作,将区间$[L,R]$拼接到去掉区间后的第$c$个数后,或者翻转$[L,R]$ Splay区间操作模板,对于区间提取操作,将$L-1$ Splay到根,再将$R+ ...

  8. Play with Chain 【HDU - 3487】【Splay+TLE讲解】

    题目链接 很好的一道题,用了三天多的时间,终于知道了我为什么T的原因,也知道了在Splay的同时该怎样子的节约时间,因为Splay本身就是大常数的O(N*logN),我们如果不在各种细节上节约时间,很 ...

  9. HDU 3487 Splay tree

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

随机推荐

  1. 37.看下图实现如下接口和类,并完成Adventure中的主方法。

    //接口Swim package jieKou; public interface ICanswim { void Swim(); } //接口Fly package jieKou; public i ...

  2. Java操作*.properties

    java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properti ...

  3. php练习1

    <?php$conn=mysqli_init();if(!conn){ echo "mysqli_init error"; exit(0);}$ret=mysqli_real ...

  4. js对象,类

    js闭包网站:http://www.cnblogs.com/qieguo/p/5457040.html 有权访问另一个函数作用域内变量的函数都是闭包. 这里 inc 函数访问了构造函数 a 里面的变量 ...

  5. IOS 导出ipa文件方法

    1.首先打开项目,Device选项栏选择“Generic iOS Device”.如下图所示: 2.选择屏幕上方的“product”并点击打开,选择“Archive”并点击打开,程序就会自动运行,运行 ...

  6. 学习笔记——责任链模式ChainOfResponsibility

    责任链模式,主要是通过自己记录一个后继者来判断当前的处理情况.Handler中,再增加一个方法用于设置后继对象,如SetHandler(Handler obj). 然后Handler类以其子类的处理方 ...

  7. 在线GET/POST API接口请求模拟测试工具

    在前后端开发过程中经常需要对HTTP接口进行测试,推荐几款比较好用的测试工具 Postman https://www.getpostman.com/ 强大的HTTP请求测试工具 支持多平台 Advan ...

  8. c语言-三字符组

    C 源程序源字符集在 7 位 ASCII 字符集中包含,但设置为 ISO 646-1983 固定的代码的超集. 三字符序列允许 C 程序编写使用 " 仅 ISO (国际标准组织的固定的代码. ...

  9. C++ 中 const和define的区别

    来源网址:http://wujiangping.blog.163.com/blog/static/195182011201255115125205/ 请区别用#define命令定义的符号常量和用con ...

  10. Linq第二讲

    这一讲,来说说集合.因为linq主要用于对数据源进行查询,集合是最常见的数据源. 集合 形式: 数组,列表List<T> Arraylist等. 特点: 可通过索引或键访问.可进行fore ...