高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 }