很多人觉得可持久化treap很慢,但是事实上只是他们可持久化treap的写法不对。他们一般是用split和merge实现所有功能,但是这样会有许多不必要的分裂。其实我们可以用一种特殊的方式来实现插入和删除。

插入:我们先随机出新建节点的Rank值,随二叉查找树的顺序找到第一个Rank比新建节点Rank小的节点,将以这个节点为根的子树按Key值分裂成两颗树并作为新建节点的左子树和右子树。

删除:我们用二叉查找树的方式找到删除节点,释放节点空间并将节点左子树和右子树合并代替原树。

由于随机构建二叉查找树从每个节点到叶节点期望距离是O(1)的,所以在插入删除中期望合并的树的深度是O(1)的。这样一来插入删除的log常数就只受查找速度影响(貌似比普通treap还快)

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<algorithm>
  4. using namespace std ;
  5.  
  6. struct Node {
  7. int Key ;
  8. int Rank ;
  9. int Size ;
  10. Node * L ;
  11. Node * R ;
  12. Node ( int , int , int ) ;
  13. void maintain () ;
  14. } ;
  15.  
  16. Node * Nil = new Node ( , INT_MIN , ) ;
  17.  
  18. Node :: Node ( const int Key = , const int Rank = ( rand () ) , const int Size = ) :
  19. Key ( Key ) , Rank ( Rank ) ,
  20. Size ( Size ) , L ( Nil ) , R ( Nil ) {}
  21.  
  22. void Node :: maintain () {
  23. Size = L -> Size + + R -> Size ;
  24. }
  25.  
  26. Node * Merge ( Node * const L , Node * const R ) {
  27. if ( L == Nil ) return R ;
  28. else if ( R == Nil ) return L ;
  29. else if ( L -> Rank > R -> Rank ) {
  30. L -> R = Merge ( L -> R , R ) ;
  31. L -> maintain () ;
  32. return L ;
  33. } else {
  34. R -> L = Merge ( L , R -> L ) ;
  35. R -> maintain () ;
  36. return R ;
  37. }
  38. }
  39.  
  40. typedef pair < Node * , Node * > Npair ;
  41.  
  42. void Split1 ( Node * const O , const int K ,
  43. Node * & L , Node * & R ) {
  44. if ( O == Nil ) L = R = Nil ;
  45. else if ( O -> L -> Size <= K ) {
  46. Split1 ( O -> L , K , L , R ) ;
  47. O -> L = R ;
  48. R = O ;
  49. O -> maintain () ;
  50. } else {
  51. Split1 ( O -> R , K - ( O -> L -> Size + ) , L , R ) ;
  52. O -> R = L ;
  53. L = O ;
  54. O -> maintain () ;
  55. }
  56. }
  57.  
  58. void Split2 ( Node * const O , const int Key ,
  59. Node * & L , Node * & R ) {
  60. if ( O == Nil ) L = R = Nil ;
  61. else if ( Key <= O -> Key ) {
  62. Split2 ( O -> L , Key , L , R ) ;
  63. O -> L = R ;
  64. R = O ;
  65. O -> maintain () ;
  66. } else {
  67. Split2 ( O -> R , Key , L , R ) ;
  68. O -> R = L ;
  69. L = O ;
  70. O -> maintain () ;
  71. }
  72. }
  73.  
  74. int GetRank ( const Node * O , const int Key ) {
  75. int ans = ;
  76. while ( O != Nil ) {
  77. if ( O -> Key <= Key ) {
  78. O = O -> L ;
  79. } else {
  80. ans += O -> L -> Size + ;
  81. O = O -> R ;
  82. }
  83. }
  84. return ans ;
  85. }
  86.  
  87. void Erase ( Node * & O , const int Key ) {
  88. if ( O == Nil ) return ;
  89. else if ( O -> Key == Key ) O = Merge ( O -> L , O -> R ) ;
  90. else if ( Key < O -> Key ) {
  91. Erase ( O -> L , Key ) ;
  92. O -> maintain () ;
  93. } else {
  94. Erase ( O -> R , Key ) ;
  95. O -> maintain () ;
  96. }
  97. }
  98.  
  99. void Insert ( Node * & O , const int Key , const int Rank = rand () ) {
  100. if ( O -> Rank < Rank ) {
  101. Node * const np = new Node ( Key ) ;
  102. Split2 ( O , Key , np -> L , np -> R ) ;
  103. ( O = np ) -> maintain () ;
  104. } else if ( Key < O -> Key ) {
  105. Insert ( O -> L , Key , Rank ) ;
  106. O -> maintain () ;
  107. } else {
  108. Insert ( O -> R , Key , Rank ) ;
  109. O -> maintain () ;
  110. }
  111. }

高rong效chang的可持久化treap的更多相关文章

  1. UVALive 6145 Version Controlled IDE(可持久化treap、rope)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  2. BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

    3595: [Scoi2014]方伯伯的Oj Time Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status ...

  3. 【模板】可持久化文艺平衡树-可持久化treap

    题目链接 题意 对于各个以往的历史版本实现以下操作: 在第 p 个数后插入数 x . 删除第 p 个数. 翻转区间 [l,r],例如原序列是 \(\{5,4,3,2,1\}\),翻转区间 [2,4] ...

  4. 可持久化Treap

    终于写了一次可持久化Treap,做的是可持久化序列的模板题. Treap Treap=Tree+Heap,是一个随机化的数据结构.它的每个节点至少有两个关键字,一个是我们要存储的\(val\),一个是 ...

  5. Codeforces - 38G 可持久化Treap 区间操作

    题意:\(n\)个人排队,每个人有重要度\(p\)和不要脸度\(c\),如果第\(i\)个人的重要度大于第\(i-1\)个人的重要度,那么他们之间可以交换,不要脸度-1,交换后先前的第\(i\)个人也 ...

  6. Codeforces - 675D 可持久化Treap 树形操作

    题意:模拟二叉树的构造过程,给出\(n\)个节点,每次从根插入,小于当前节点转到左儿子,否则右儿子,输出第\([2,n]\)个节点的父亲的权值 直接手动模拟会被链式结构T掉 网上找了下发现二叉树的性质 ...

  7. 平衡树与可持久化treap

    平衡树(二叉树) 线段树不支持插入or删除一个数于是平衡树产生了 常见平衡树:treap(比sbt慢,好写吧),SBT(快,比较好写,有些功能不支持),splay(特别慢,复杂度当做根号n来用,功能强 ...

  8. 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree2

    试了一下先上再下的Treap方式,很高兴,代码变短了,但是,跑的变慢了!!!其实慢得不多,5%左右.而且这个版本的写法不容易写错..只要会一般可持久化Treap的人写着都不难...就是相对于(压行的) ...

  9. 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree

    一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现 ...

随机推荐

  1. 【HEOI2016】排序

    题面 题解 这题好神仙啊... 我们二分这个位置上的数, 然后当\(val[i] \geq mid\)的位置设为\(1\),否则为\(0\) 这样一来,这道题就变成了一个\(01\)序列排序,所以就可 ...

  2. Docker入门篇(一)之docker基础

    1.Docker 架构 http://blog.csdn.net/u012562943/article/category/6048991/1Docker 使用客户端-服务器 (C/S) 架构模式,使用 ...

  3. apache-kylin-2.5.2-bin-cdh57与cdh-5.13.0集群整合运用

    1.下载kylin最新版apache-kylin-2.5.2-bin-cdh57: 2.解压配置环境变量: export BASE_PATH="/opt/cloudera/parcels/C ...

  4. Windows下Mongodb安装部署

    1.下载安装包 mongodb-win32-x86_64-enterprise-windows-64-3.6.4.zip 解压 安装失败(当前环境windows server2012 R2):已验证可 ...

  5. docker部署war包到阿里云

    最近买了个阿里云服务器,配置1核2g内存,学习够了.记录下过程. 1,服务器相关,请看下图,云服务器主要配置是安全组和密钥,前者是开放端口,后者可以用于远程连接(比如我windows系统通过putty ...

  6. Eclipse用java.util.Scanner时出现Resource leak: 'in' is never closed

    Resource leak: 'in' is never closed : 直译为资源泄漏,‘in’一直没被关闭. 由于声明了数据输入扫描仪(Scanner in),从而获得了配置内存,但是结束时却没 ...

  7. JavaScript事件冒泡和捕获

    事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上的去触发事件. 绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获.true,事件捕获:fa ...

  8. text-align与vertical-align属性的区别

    1.text-align属性设置元素在水平方向(x轴)的位置 text-align:left://文本居左 text-align:center://文本居中 text-align:right: //文 ...

  9. 20135208JAVA第二次试验

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1352 姓名:贺邦  学号:20135208 成绩:             指导教师:娄嘉鹏  ...

  10. RIGHT-BICEP测试第二次程序

    根据Right-BICEP单元测试的方法我对我写的第二次程序进行了测试: 测试一:测试能否控制使用乘除 测试二:测试是否能加括号 测试三:是否可以控制题目输出数量 测试四:能否控制输出方式,选择文件输 ...