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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM