平衡树学习
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 }
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 }
【模板】文艺平衡树(题目):
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 }
【模板】二逼平衡树(题目):
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 }
这题目就离谱
以上是关于平衡树学习的主要内容,如果未能解决你的问题,请参考以下文章