高rong效chang的可持久化treap

很多人觉得可持久化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 ( 0 , INT_MIN , 0 ) ;
 17 
 18 Node :: Node ( const int Key = 0 , const int Rank = ( rand () ) , const int Size = 1 ) :
 19 Key ( Key ) , Rank ( Rank ) , 
 20 Size ( Size ) , L ( Nil ) , R ( Nil ) {}
 21 
 22 void Node :: maintain () {
 23     Size = L -> Size + 1 + 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 + 1 ) , 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 = 0 ;
 76     while ( O != Nil ) {
 77         if ( O -> Key <= Key ) {
 78             O = O -> L ;
 79         } else {
 80             ans += O -> L -> Size + 1 ; 
 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 }

 

posted @ 2016-05-18 15:27  Chris_2  阅读(1272)  评论(6编辑  收藏  举报