1. 程式人生 > >範浩強treap——可持久化

範浩強treap——可持久化

urn std log 可持久化 大於 merge node 合並 如果

當平衡樹需要可持久化的時候,意味著我們需要訪問以前的某個時間點的平衡樹,就要保持以前的樹形態不變,新建一個時間戳,構建一棵新的樹。

如果用以前的旋轉treap可能就不方便做到(又要打時間戳,又要新建節點,又要旋轉),而且涉及到旋轉,空間可能會承受不住,我們需要用到一種新的平衡樹——fhq treap

這是一種非常好寫的treap 核心操作有兩個,一個是split一個是merge。

split(node,k,x,y) 意思是把以node為跟的子樹分成兩部分,一部分小於等於k(根為x),一部分大於k(根為y)。在可持久化的時候要保證以前的樹的形態不變,就要每一次copy一個節點過來。

而我們每一次遞歸只會訪問一個節點的左右子樹中的一個節點,又因為treap的均攤深度為log,所以總體的空間為nlogn,是非常高效的。

說完split接下來是merge

merge函數,是有返回值的,merge(x,y) 是把以x為根的子樹和以y為根的子樹合並起來,返回這棵新的樹的根,遞歸的實現,非常好懂。

接下來的所有操作都是基於以上兩個核心的操作,非常好理解,比旋轉的treap好理解而且更好寫,註意可持久化即可。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=500005;
  4 struct node
  5 {
  6     int ch[2];
  7     int fix,key,sz;
  8 }t[N*50
]; 9 int root[N],cnt=1; 10 int copynode(int x) 11 { 12 cnt++; 13 t[cnt]=t[x]; 14 return cnt; 15 } 16 void update(int cur) 17 { 18 if(cur) 19 t[cur].sz=t[t[cur].ch[0]].sz+t[t[cur].ch[1]].sz+1; 20 } 21 int newnode(int val) 22 { 23 cnt++; 24 t[cnt].ch[0]=t[cnt].ch[1
]=0; 25 t[cnt].key=val; 26 t[cnt].sz=1; 27 t[cnt].fix=rand(); 28 return cnt; 29 } 30 void split(int now,int k,int &x,int &y) 31 { 32 if(!now) x=y=0; 33 else 34 { 35 if(t[now].key<=k) 36 { 37 x=copynode(now); 38 split(t[x].ch[1],k,t[x].ch[1],y); 39 } 40 else 41 { 42 y=copynode(now); 43 split(t[y].ch[0],k,x,t[y].ch[0]); 44 } 45 update(x); 46 update(y); 47 } 48 } 49 int merge(int x,int y) 50 { 51 if(!x||!y) return x+y; 52 if(t[x].fix<t[y].fix) 53 { 54 int r=copynode(x); 55 t[r].ch[1]=merge(t[r].ch[1],y); 56 update(r); 57 return r; 58 } 59 else 60 { 61 int r=copynode(y); 62 t[r].ch[0]=merge(x,t[r].ch[0]); 63 update(r); 64 return r; 65 } 66 } 67 void insert(int bb,int val) 68 { 69 int x,y,z; 70 x=y=z=0; 71 split(root[bb],val,x,y); 72 z=newnode(val); 73 root[bb]=merge(merge(x,z),y); 74 } 75 void Delete(int bb,int val) 76 { 77 int x,y,z; 78 split(root[bb],val,x,z); 79 split(x,val-1,x,y); 80 y=merge(t[y].ch[0],t[y].ch[1]); 81 root[bb]=merge(merge(x,y),z); 82 } 83 int getpos(int now,int k) 84 { 85 while(1) 86 { 87 if(k<=t[t[now].ch[0]].sz) now=t[now].ch[0]; 88 else if(k==t[t[now].ch[0]].sz+1) return now; 89 else k-=t[t[now].ch[0]].sz+1,now=t[now].ch[1]; 90 } 91 } 92 int getkth(int bb,int val) 93 { 94 int x,y; 95 int ret; 96 split(root[bb],val-1,x,y); 97 ret=t[x].sz+1; 98 return ret; 99 } 100 int getval(int now,int k) 101 { 102 int x; 103 x=getpos(now,k); 104 return t[x].key; 105 } 106 int getpre(int bb,int val) 107 { 108 int x,y; 109 int k,ret; 110 split(root[bb],val-1,x,y); 111 if(x) k=t[x].sz; 112 else return -2147483647; 113 ret=getval(x,k); 114 return ret; 115 } 116 int getnext(int bb,int val) 117 { 118 int x,y; 119 split(root[bb],val,x,y); 120 if(!y) return 2147483647; 121 int ret=getval(y,1); 122 return ret; 123 } 124 int main() 125 { 126 int n,bb,cmd,val; 127 scanf("%d",&n); 128 for(int i=1;i<=n;++i) 129 { 130 scanf("%d%d%d",&bb,&cmd,&val); 131 root[i]=root[bb]; 132 switch(cmd) 133 { 134 case 1:insert(i,val);break; 135 case 2:Delete(i,val);break; 136 case 3:printf("%d\n",getkth(i,val));break; 137 case 4:printf("%d\n",getval(root[i],val));break; 138 case 5:printf("%d\n",getpre(i,val));break; 139 case 6:printf("%d\n",getnext(i,val));break; 140 } 141 } 142 }

範浩強treap——可持久化