第一棵伸展树,各种调试模板……TVT

对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error。

后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 这两个节点,并且每次截取翻转添加到序列最后,因此无法确定 n+1 这个节点在序列的哪个位置。

比如(括号中的为添加的冗余节点):

(0) 1 2 3 4 5 (6)

我把[3,4]截取翻转添加到序列尾部,会变成这样:

(0)1 2 5 (6)4 3

此时我如果再希望截取[3,4],期望的结果应该是:

1 2 3 4 5

而实际上会变成:

(0)1 2 4 3 (6) 5

我用了一种挺麻烦的方式解决的这个问题:

就是让伸展树在冗余节点n+1之前的位置再分裂一次,每次把截取的序列添加到节点n+1的前面,一直维持n+1在序列最末尾,这样就不会有干扰了。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. struct Node
  9. {
  10. Node *ch[];
  11. int v, s;
  12. int flip;
  13. Node( int v ):v(v)
  14. {
  15. ch[] = ch[] = NULL;
  16. s = ;
  17. flip = ;
  18. }
  19. int cmp( int x ) const
  20. {
  21. int t = ( ch[] == NULL ) ? : ch[]->s;
  22. if ( t >= x ) return ;
  23. if ( t + == x ) return -;
  24. return ;
  25. }
  26. void maintain()
  27. {
  28. s = ;
  29. if ( ch[] != NULL ) s += ch[]->s;
  30. if ( ch[] != NULL ) s += ch[]->s;
  31. return;
  32. }
  33. void pushDown()
  34. {
  35. if ( flip )
  36. {
  37. flip = ;
  38. swap( ch[], ch[] );
  39. if ( ch[] != NULL ) ch[]->flip = !ch[]->flip;
  40. if ( ch[] != NULL ) ch[]->flip = !ch[]->flip;
  41. }
  42. }
  43. };
  44.  
  45. int n, m;
  46.  
  47. void Rotate( Node* &o, int d ) //d=0 左旋 d=1 右旋
  48. {
  49. Node *k = o->ch[ d ^ ];
  50. o->ch[ d ^ ] = k->ch[d];
  51. k->ch[d] = o;
  52. o = k;
  53. o->ch[d]->maintain();
  54. o->maintain();
  55. return;
  56. }
  57.  
  58. void splay( Node* &o, int k )
  59. {
  60. o->pushDown();
  61. int d = o->cmp(k);
  62. if ( d == )
  63. {
  64. if ( o->ch[] != NULL )
  65. k -= o->ch[]->s;
  66. --k;
  67. }
  68. if ( d != - )
  69. {
  70. Node *p = o->ch[d];
  71. p->pushDown();
  72. int d2 = p->cmp(k);
  73. int k2 = k;
  74. if ( d2 == )
  75. {
  76. if ( p->ch[] != NULL )
  77. k2 -= p->ch[]->s;
  78. --k2;
  79. }
  80. if ( d2 != - )
  81. {
  82. splay( p->ch[d2], k2 );
  83. if ( d == d2 ) Rotate( o, d ^ );
  84. else Rotate( o->ch[d], d );
  85. }
  86. Rotate( o, d ^ );
  87. }
  88. return;
  89. }
  90.  
  91. Node *Merge( Node *left, Node *right )
  92. {
  93. splay( left, left->s );
  94. left->ch[] = right;
  95. left->maintain();
  96. return left;
  97. }
  98.  
  99. void Split( Node *o, int k, Node* &left, Node* &right )
  100. {
  101. splay( o, k );
  102. left = o;
  103. right = o->ch[];
  104. o->ch[] = NULL;
  105. left->maintain();
  106. return;
  107. }
  108.  
  109. void build( Node* &o, int l, int r )
  110. {
  111. int m = ( l + r ) >> ;
  112. o = new Node(m);
  113. if ( l < m ) build( o->ch[], l, m - );
  114. if ( r > m ) build( o->ch[], m + , r );
  115. o->maintain();
  116. return;
  117. }
  118.  
  119. void DFS( Node *cur )
  120. {
  121. cur->pushDown();
  122. if ( cur->ch[] ) DFS( cur->ch[] );
  123. if ( cur->v && cur->v != n + ) printf( "%d\n", cur->v );
  124. if ( cur->ch[] ) DFS( cur->ch[] );
  125. return;
  126. }
  127.  
  128. void DeleteTree( Node *cur )
  129. {
  130. if ( cur->ch[] ) DeleteTree( cur->ch[] );
  131. if ( cur->ch[] ) DeleteTree( cur->ch[] );
  132. delete cur;
  133. return;
  134. }
  135.  
  136. Node *root;
  137.  
  138. int main()
  139. {
  140. while ( ~scanf( "%d%d", &n, &m ) )
  141. {
  142. root = NULL;
  143. build( root, , n + ); //前后各加了一个冗余节点
  144. while ( m-- )
  145. {
  146. int a, b;
  147. scanf( "%d%d", &a, &b );
  148. Node *left, *mid, *right, *o, *tmp;
  149.  
  150. Split( root, a, left, o );
  151. Split( o, b - a + , mid, right );
  152.  
  153. if ( right->s - > )
  154. {
  155. Split( right, right->s - , tmp, o );
  156. mid->flip ^= ;
  157. root = Merge( left, Merge( Merge( tmp, mid ), o ) );
  158. }
  159. else
  160. {
  161. mid->flip ^= ;
  162. root = Merge( left, Merge( mid, right ) );
  163. }
  164. }
  165. DFS( root );
  166. DeleteTree( root );
  167. }
  168. return ;
  169. }

UVa 11922 - Permutation Transformer 伸展树的更多相关文章

  1. UVA 11922 Permutation Transformer —— splay伸展树

    题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...

  2. UVA 11922 Permutation Transformer(平衡二叉树)

    Description Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. ...

  3. UVA 11922 Permutation Transformer(Splay Tree)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...

  4. UVA 11922 Permutation Transformer (Splay树)

    题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...

  5. uva 11922 - Permutation Transformer

    splay的题: 学习白书上和网上的代码敲的: #include <cstdio> #include <cstring> #include <cstdlib> #i ...

  6. UVA - 11922 Permutation Transformer (splay)

    题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...

  7. uva 11922 Permutation Transforme/splay tree

    原题链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 伸展树的区间翻转剪切... 如下: #include< ...

  8. uva 12003 Array Transformer (线段树套平衡树)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  9. UVA 11525 Permutation ——(线段树,脑筋急转弯)

    只要注意到对于譬如:S1*(k-1)! 因为后面k-1个数字的全排列个数刚好是(k-1)!,那么第一个数字就是没有取过的数字的第(S1+1)个即可.取走这个数字以后这个数字就不能再用了,依次类推即可得 ...

随机推荐

  1. hadoop的核心思想

    hadoop的核心思想 1.1.1. hadoop的核心思想 Hadoop包括两大核心,分布式存储系统和分布式计算系统. 1.1.1.1. 分布式存储 为什么数据需要存储在分布式的系统中哪,难道单一的 ...

  2. Session设置不当导致API变成单线程问题的解决

    起因: 最近开发一个项目,有个接口很慢(数据库的问题),然后在执行期间,随手去点了其他功能(调用其他接口),发现不响应了.等那个很慢的接口返回结果了,这个功能才立马返回结果.  这明显是一个问题啊! ...

  3. JPA学习---第六节:大数据字段映射与字段延迟加载

    1.大数据字段所需的注解 @Lob ,例如: @Lobprivate String info; 在mysql中映射产生的字段的类型是longtext:在oracle中是  CLOB @Lobpriva ...

  4. app进入后台申请10分钟活跃时间-b

    IOS允许长时间在后台运行的情况有7种: audio VoIP GPS 下载新闻 和其它附属硬件进行通讯时 使用蓝牙进行通讯时 使用蓝牙共享数据时 除以上情况,程序退出时可能设置短暂运行10分钟 让程 ...

  5. .net 自然排序方式

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  6. 2437: [Noi2011]兔兔与蛋蛋 - BZOJ

    Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...

  7. Remote Desktop manager 连接后无法自动登录

    现象: Remote Desktop manager 连接后无法自动登录 用Windows 自带的远程桌面 可以自动登录 解决方法: 在指定站点 右键 Edit Entry. 如下图处打勾就可以了.

  8. 【Asp.Net MVC--资料汇总】杂七杂八

    Html.RenderPartial与Html.RenderAction的区别 http://blog.sina.com.cn/s/blog_8278b1800100zkn0.html ASP.NET ...

  9. 【EntityFramwork--处理数据并发问题】

    EntityFramwork--处理数据并发问题时支持乐观并发,即假定最佳场景(这里是指数据在更新过程中没有发生变化) 具体看<Beginning ASP.NET 4.5 Databases&g ...

  10. vc6命令行编译工程方法

    查vc++ 6.0 的 msdn找到下面的命令: msdev FileName [/MAKE "ProjectName – ConfigName | ALL"] [/REBUILD ...