范浩强treap——可持久化
生活随笔
收集整理的這篇文章主要介紹了
范浩强treap——可持久化
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
當平衡樹需要可持久化的時候,意味著我們需要訪問以前的某個時間點的平衡樹,就要保持以前的樹形態不變,新建一個時間戳,構建一棵新的樹。
如果用以前的旋轉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好理解而且更好寫,注意可持久化即可。
——by VANE
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
",getkth(i,val));break;
137 case 4:printf("%d
",getval(root[i],val));break;
138 case 5:printf("%d
",getpre(i,val));break;
139 case 6:printf("%d
",getnext(i,val));break;
140 }
141 }
142 }
生命中真正重要的不是你遭遇了什么,而是你記住了哪些事,又是如何銘記的。
總結
以上是生活随笔為你收集整理的范浩强treap——可持久化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么Kubernetes要引入pod的
- 下一篇: 使用postman和SAP C4C OD