平衡树学习

Posted arrogant-hierarch

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树学习相关的知识,希望对你有一定的参考价值。

Splay:

  像BST(二叉搜索树)一样插入查询,可以改变树的形状,可以区间翻转,可以实现动态树,不可持久化。

核心代码:

技术图片
 1 void rotate(int a) // 旋转
 2 {
 3     int b = fa[a], c = fa[b];
 4     int k = son[b][1] == a, w = son[a][!k];
 5 
 6     if (no_root(b)) son[c][son[c][1] == b] = a;
 7     son[a][!k] = b;
 8     son[b][k] = w;
 9 
10     if (w) fa[w] = b;
11     fa[b] = a;
12     fa[a] = c;
13     pushup(b);
14 }
15 
16 void splay(int x) // 将x移动到splay的根
17 {
18     int y = x, z = 0;
19     stk[++z] = y;
20 
21     while (no_root(y)) stk[++z] = y = fa[y];
22     while (z) pushdown(stk[z--]);
23 
24     while (no_root(x))
25     {
26         y = fa[x]; z = fa[y];
27         if (no_root(y)) rotate((son[y][0] == x) ^ (son[z][0] == y) ? x : y);
28         rotate(x);
29     }
30     pushup(x);
31 }
View Code

 

Treap:

 

  具有堆性质的BST,每个点有两个关键字,一个key为原来BST维护的值,一个fix

值,一个节点新建时,给予它一个随机的fix值,以fix为关键字构成最小根,Treap的期望高度为O(log  n)。

 

【模板】普通平衡树(题目):

技术图片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 2000010, INF = 1e9 + 7;
  8 
  9 int root;
 10 
 11 struct Node
 12 {
 13     int l, r, val, size, dat, cnt;
 14     Node() {}
 15     Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {}
 16 };
 17 
 18 int cnt;
 19 Node tr[N];
 20 
 21 int New(int x)
 22 {
 23     tr[++cnt] = Node(0, 0, x, 1, 1);
 24     tr[cnt].dat = rand();
 25     return cnt;
 26 }
 27 
 28 void update(int q)
 29 {
 30     tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size;
 31 }
 32 
 33 void build()
 34 {
 35     New(-INF), New(INF);
 36     root = 1;
 37     tr[1].r = 2;
 38     update(root);
 39 }
 40 
 41 void zig(int &q) // 右旋
 42 {
 43     int p = tr[q].l;
 44     tr[q].l = tr[p].r;
 45     tr[p].r = q;
 46     q = p;
 47 
 48     update(tr[q].r);
 49     update(q);
 50 }
 51 
 52 void zag(int& q)
 53 {
 54     int p = tr[q].r;
 55     tr[q].r = tr[p].l;
 56     tr[p].l = q;
 57     q = p;
 58 
 59     update(tr[q].l);
 60     update(q);
 61 }
 62 
 63 
 64 void insert(int& q, int x)
 65 {
 66     if (!q)
 67     {
 68         q = New(x);
 69         return;
 70     }
 71 
 72     if (x == tr[q].val)
 73     {
 74         tr[q].cnt++;
 75         update(q);
 76         return;
 77     }
 78 
 79     if (x < tr[q].val)
 80     {
 81         insert(tr[q].l, x);
 82         if (tr[q].dat < tr[tr[q].l].dat) zig(q);
 83     }
 84     else
 85     {
 86         insert(tr[q].r, x);
 87         if (tr[q].dat < tr[tr[q].r].dat) zag(q);
 88     }
 89     update(q);
 90 }
 91 
 92 void Delete(int &q, int x)
 93 {
 94     if (!q) return;
 95     if (x == tr[q].val)
 96     {
 97         if (tr[q].cnt > 1)
 98         {
 99             tr[q].cnt--;
100             update(q);
101             return;
102         }
103         if (tr[q].l || tr[q].r)
104         {
105             if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x);
106             else zag(q), Delete(tr[q].l, x);
107             update(q);
108         }
109         else q = 0;
110         return;
111     }
112 
113     if (x < tr[q].val) Delete(tr[q].l, x);
114     else Delete(tr[q].r, x);
115     update(q);
116 }
117 
118 int find_rank(int q, int x)
119 {
120     if (!q) return 0;
121     if (x == tr[q].val) return tr[tr[q].l].size + 1;
122     if (x < tr[q].val) return find_rank(tr[q].l, x);
123     else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size;
124 }
125 
126 int find_num(int q, int x)
127 {
128     if (!q) return INF;
129     if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x);
130     if (x <= tr[tr[q].l].size + tr[q].cnt) return tr[q].val;
131     return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt);
132 }
133 
134 int find_befor(int x)
135 {
136     int ans = 1, q = root;
137     while (q)
138     {
139         if (x == tr[q].val)
140         {
141             if (tr[q].l > 0)
142             {
143                 q = tr[q].l;
144                 while (tr[q].r > 0) q = tr[q].r;
145                 ans = q;
146             }
147             break;
148         }
149         if (tr[q].val<x && tr[q].val>tr[ans].val) ans = q;
150         if (x < tr[q].val) q = tr[q].l;
151         else q = tr[q].r;
152     }
153     return tr[ans].val;
154 }
155 
156 int find_nex(int x)
157 {
158     int ans = 2, q = root;
159     while (q)
160     {
161         if (x == tr[q].val)
162         {
163             if (tr[q].r > 0)
164             {
165                 q = tr[q].r;
166                 while (tr[q].l > 0) q = tr[q].l;
167                 ans = q;
168             }
169             break;
170         }
171         if (tr[q].val>x && tr[q].val<tr[ans].val) ans = q;
172         if (x < tr[q].val) q = tr[q].l;
173         else q = tr[q].r;
174     }
175     return tr[ans].val;
176 }
177 
178 int main()
179 {
180     build();
181 
182     int q;
183     scanf("%d", &q);
184     while (q--)
185     {
186         int op, x;
187         scanf("%d%d", &op, &x);
188         switch (op) 
189         {
190         case 1:
191         {
192             insert(root, x);
193             break;
194         }
195         case 2:
196         {
197             Delete(root, x);
198             break;
199         }
200         case 3:
201         {
202             printf("%d
", find_rank(root, x) - 1);
203             break;
204         }
205         case 4:
206         {
207             printf("%d
", find_num(root, x + 1));
208             break;
209         }
210         case 5:
211         {
212             printf("%d
", find_befor(x));
213             break;
214         }
215 
216         case 6:
217         {
218             printf("%d
", find_nex(x));
219             break;
220         }
221         }
222     }
223 }
View Code

 

【模板】文艺平衡树(题目):

技术图片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int N = 2000010;
  9 
 10 int n;
 11 int w[N];
 12 int lazy[N];
 13 int root;
 14 
 15 vector<int> ans;
 16 
 17 struct Node
 18 {
 19     int son[2], fa, val, size;
 20     Node() {}
 21 };
 22 
 23 Node tr[N];
 24 
 25 void update(int q)
 26 {
 27     tr[q].size = tr[tr[q].son[0]].size + tr[tr[q].son[1]].size + 1;
 28 }
 29 
 30 int build(int l, int r, int f)
 31 {
 32     int q = (l + r) >> 1;
 33     tr[q].fa = f;
 34     tr[q].val = w[q];
 35 
 36     if (l < q) tr[q].son[0] = build(l, q - 1, q);
 37     if (r > q) tr[q].son[1] = build(q + 1, r, q);
 38     update(q);
 39     return q;
 40 }
 41 
 42 void pushdown(int x)
 43 {
 44     if (!lazy[x]) return;
 45 
 46     lazy[tr[x].son[0]] ^= 1;
 47     lazy[tr[x].son[1]] ^= 1;
 48     swap(tr[x].son[0], tr[x].son[1]);
 49     lazy[x] = 0;
 50 }
 51 
 52 int find1(int x)
 53 {
 54     int q = root;
 55     while (true)
 56     {
 57         pushdown(q);
 58         if (tr[q].son[0] && tr[tr[q].son[0]].size >= x) q = tr[q].son[0];
 59         else
 60         {
 61             int rank = (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + 1;
 62             if (x <= rank) return q;
 63             x -= rank;
 64             q = tr[q].son[1];
 65         }
 66     }
 67 }
 68 
 69 void rotate(int x)
 70 {
 71     int y = tr[x].fa, z = tr[y].fa, k = tr[y].son[1] == x, w = tr[x].son[!k];
 72 
 73     if (z) tr[z].son[tr[z].son[1] == y] = x;
 74     else root = x;
 75     tr[y].son[k] = w;
 76     tr[x].son[!k] = y;
 77 
 78     if (w) tr[w].fa = y;
 79     tr[x].fa = z;
 80     tr[y].fa = x;
 81     update(y);
 82     update(x);
 83 }
 84 
 85 void splay(int x, int f)
 86 {
 87     while (tr[x].fa != f)
 88     {
 89         int y = tr[x].fa, z = tr[y].fa;
 90         if (z != f) rotate(((tr[y].son[1] == x) ^ (tr[z].son[1] == y)) ? x : y);
 91         rotate(x);
 92     }
 93 }
 94 
 95 void print(int x)
 96 {
 97     pushdown(x);
 98     if (tr[x].son[0]) print(tr[x].son[0]);
 99     ans.push_back(tr[x].val);
100     if (tr[x].son[1]) print(tr[x].son[1]);
101 }
102 
103 int main()
104 {
105     int q;
106     scanf("%d%d", &n,&q);
107 
108     for (int i = 1; i <= n + 2; i++) w[i] = i - 1;
109 
110     root = build(1, n + 2, 0);
111 
112     while (q--)
113     {
114         int l, r;
115         scanf("%d%d", &l, &r);
116         l = find1(l), r = find1(r + 2);
117         splay(l, 0), splay(r, l);
118         lazy[tr[tr[root].son[1]].son[0]] ^= 1;
119     }
120 
121     print(root);
122     for (int i = 0; i < n; i++) printf("%d ", ans[i + 1]);
123 }
View Code

 

【模板】二逼平衡树(题目):

技术图片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N = 2000010, INF = 2147483647;
  8 
  9 int n;
 10 int a[N];
 11 
 12 struct Treap
 13 {
 14     struct Node
 15     {
 16         int l, r, val, size, dat, cnt;
 17         Node() {}
 18         Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {}
 19     };
 20 
 21     int cnt;
 22     Node tr[N];
 23 
 24     int New(int x)
 25     {
 26         tr[++cnt] = Node(0, 0, x, 1, 1);
 27         tr[cnt].dat = rand();
 28         return cnt;
 29     }
 30 
 31     void update(int q)
 32     {
 33         tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size;
 34     }
 35 
 36     void zig(int& q) // 右旋
 37     {
 38         int p = tr[q].l;
 39         tr[q].l = tr[p].r;
 40         tr[p].r = q;
 41         q = p;
 42 
 43         update(tr[q].r);
 44         update(q);
 45     }
 46 
 47     void zag(int& q)
 48     {
 49         int p = tr[q].r;
 50         tr[q].r = tr[p].l;
 51         tr[p].l = q;
 52         q = p;
 53 
 54         update(tr[q].l);
 55         update(q);
 56     }
 57 
 58     void insert(int& q, int x)
 59     {
 60         if (!q)
 61         {
 62             q = New(x);
 63             update(q);
 64             return;
 65         }
 66 
 67         if (x == tr[q].val)
 68         {
 69             tr[q].cnt++;
 70             update(q);
 71             return;
 72         }
 73 
 74         if (x < tr[q].val)
 75         {
 76             insert(tr[q].l, x);
 77             if (tr[q].dat < tr[tr[q].l].dat) zig(q);
 78         }
 79         else
 80         {
 81             insert(tr[q].r, x);
 82             if (tr[q].dat < tr[tr[q].r].dat) zag(q);
 83         }
 84         update(q);
 85     }
 86 
 87     void Delete(int& q, int x)
 88     {
 89         if (!q) return;
 90         if (x == tr[q].val)
 91         {
 92             if (tr[q].cnt > 1)
 93             {
 94                 tr[q].cnt--;
 95                 update(q);
 96                 return;
 97             }
 98             if (tr[q].l || tr[q].r)
 99             {
100                 if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x);
101                 else zag(q), Delete(tr[q].l, x);
102                 update(q);
103             }
104             else q = 0;
105             return;
106         }
107         else if (x < tr[q].val) Delete(tr[q].l, x);
108         else Delete(tr[q].r, x);
109         
110         if(q) update(q);
111     }
112 
113     int find_rank(int q, int x)
114     {
115         if (!q) return 0;
116         if (x == tr[q].val) return tr[tr[q].l].size;
117         else if (x < tr[q].val) return find_rank(tr[q].l, x);
118         else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size;
119     }
120 
121     int find_num(int q, int x)
122     {
123         if (!q) return INF;
124         if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x);
125         else if (x <= tr[tr[q].l].size + 1) return tr[q].val;
126         return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt);
127     }
128 
129     int find_pre(int p, int k)
130     {
131         if (!p) return -INF;
132         if (tr[p].val >= k) return find_pre(tr[p].l, k);
133         else return max(tr[p].val, find_pre(tr[p].r, k));
134     }
135 
136     int find_next(int p, int k)
137     {
138         if (!p) return INF;
139         if (tr[p].val <= k) return find_next(tr[p].r, k);
140         else return min(tr[p].val, find_next(tr[p].l, k));
141     }
142 };
143 
144 Treap treap;
145 
146 struct SEG
147 {
148     int root[N];
149 
150     void build(int q, int l, int r)
151     {
152         for (int i = l; i <= r; i++)
153         {
154             treap.insert(root[q], a[i]);
155         }
156 
157         if (l == r) return;
158         int mid = (l + r) >> 1;
159         build(q << 1, l, mid);
160         build(q << 1 | 1, mid + 1, r);
161     }
162 
163     int find_rank(int q, int l, int r, int L, int R, int x)
164     {
165         if (L > r || R < l) return 0;
166         if (L <= l && r <= R) return treap.find_rank(root[q], x);
167 
168         int mid = (l + r) >> 1;
169         return  find_rank(q << 1, l, mid, L, R, x) + find_rank(q << 1 | 1, mid + 1, r, L, R, x);
170     }
171 
172     int find_num(int L, int R, int k)
173     {
174         int l = 0, r = 1e8;
175         while (l < r)
176         {
177             int mid = (l + r + 1) >> 1;
178             if (find_rank(1, 1, n, L, R, mid) < k) l = mid;
179             else r = mid - 1;
180         }
181         return r;
182     }
183 
184     void modify(int q, int l, int r, int x, int k)
185     {
186         treap.Delete(root[q], a[x]);
187         treap.insert(root[q], k);
188 
189         if (l == r) return;
190 
191         int mid = (l + r) >> 1;
192         if (x <= mid) modify(q << 1, l, mid, x, k);
193         else modify(q << 1 | 1, mid + 1, r, x, k);
194     }
195 
196     int find_pre(int q, int l, int r, int L, int R, int x)
197     {
198         if (L > r || l > R) return -INF;
199         int mid = (l + r) >> 1;
200         if (L <= l && r <= R) return treap.find_pre(root[q], x);
201         else return max(find_pre(q << 1, l, mid, L, R, x), find_pre(q << 1 | 1, mid + 1, r, L, R, x));
202     }
203 
204     int find_next(int q, int l, int r, int L, int R, int x)
205     {
206         if (L > r || l > R) return INF;
207         int mid = (l + r) >> 1;
208         if (L <= l && r <= R) return treap.find_next(root[q], x);
209         else return min(find_next(q << 1, l, mid, L, R, x), find_next(q << 1 | 1, mid + 1, r, L, R, x));
210     }
211 };
212 
213 SEG seg;
214 
215 int main()
216 {
217     int m;
218     scanf("%d%d", &n, &m);
219     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
220 
221     seg.build(1, 1, n);
222 
223     while (m--)
224     {
225         int op;
226         scanf("%d", &op);
227         if (op == 1)
228         {
229             int l, r, k;
230             scanf("%d%d%d", &l, &r, &k);
231             printf("%d
", seg.find_rank(1, 1, n, l, r, k) + 1);
232         }
233         if (op == 2)
234         {
235             int l, r, k;
236             scanf("%d%d%d", &l, &r, &k);
237             printf("%d
", seg.find_num(l, r, k));
238         }
239         if (op == 3)
240         {
241             int pos, k;
242             scanf("%d%d", &pos, &k);
243             seg.modify(1, 1, n, pos, k);
244             a[pos] = k;
245         }
246         if (op == 4)
247         {
248             int l, r, k;
249             scanf("%d%d%d", &l, &r, &k);
250             printf("%d
", seg.find_pre(1, 1, n, l, r, k));
251         }
252         if (op == 5)
253         {
254             int l, r, k;
255             scanf("%d%d%d", &l, &r, &k);
256             printf("%d
", seg.find_next(1, 1, n, l, r, k));
257         }
258     }
259 }
View Code

这题目就离谱

以上是关于平衡树学习的主要内容,如果未能解决你的问题,请参考以下文章

平衡树 学习笔记

平衡树学习

学习数据结构笔记(12) --- [平衡二叉搜索树(AVLTREE)]

算法学习:伸展树(splay)

AVL平衡树(非指针实现)

平衡树学习笔记