平衡の树
平衡树
BST就是所谓的二叉平衡搜索树者也!
满足性质:中序遍历是单调递增的。
Splay Tree:
伸展树,先%%% Tarjan。
依靠旋转来维护,主要是靠splay里面的双旋。
反正我写个模板就打了220行,有剧毒......
主要函数有rotate,splay,getNbyV,insert,del等。
下面这个是一个简单的维护数的splay。
有两种插入方式,递归版亲测比非递归快一些,还能沿途更新,就是害怕爆栈,最好随时splay几下防止退化。
[update] 洛谷加了一组数据,递归版插入被hack了,非递归安然无恙。
支持重复数据,不支持pushdown,不支持空间回收。
1 #include <cstdio> 2 #define ot printf("root = %d Splay: ", spt.val[spt.root]);spt.out(spt.root);printf("\n") 3 const int N = 1000010, INF = 0x3f3f3f3f; 4 5 struct SplayTree { 6 int s[N][2], fa[N], cnt[N], siz[N], val[N]; 7 int tot, root; 8 inline void init() { 9 tot = 2; 10 root = 1; 11 fa[2] = 1; 12 s[1][1] = 2; 13 val[1] = -INF; 14 val[2] = INF; 15 siz[1] = 2; 16 siz[2] = 1; 17 cnt[1] = cnt[2] = 1; 18 return; 19 } 20 SplayTree() { 21 init(); 22 } 23 inline void clear() { 24 for(int i = 1; i <= tot; i++) { 25 fa[i] = cnt[i] = siz[i] = val[i] = 0; 26 s[i][1] = s[i][0] = 0; 27 } 28 init(); 29 return; 30 } 31 32 inline void pushup(int x) { 33 siz[x] = siz[s[x][1]] + siz[s[x][0]] + cnt[x]; 34 return; 35 } 36 inline void pushdown(int x) { 37 return; 38 } 39 40 inline void rotate(int x) { 41 int y = fa[x]; 42 int z = fa[y]; 43 bool f = (s[y][1] == x); 44 //pushdown(y); 45 //pushdown(x); 46 47 if(z) { 48 s[z][s[z][1] == y] = x; 49 } 50 fa[x] = z; 51 fa[s[x][!f]] = y; 52 s[y][f] = s[x][!f]; 53 fa[y] = x; 54 s[x][!f] = y; 55 56 pushup(y); 57 pushup(x); 58 if(!z) { 59 root = x; 60 } 61 return; 62 } 63 64 inline void splay(int x, int g) { 65 int y = fa[x]; 66 int z = fa[y]; 67 while(y != g) { 68 if(z != g) { /// if(z) if(z != root) 69 (s[z][1] == y) ^ (s[y][1] == x) 70 ? rotate(x) : rotate(y); 71 } 72 rotate(x); 73 y = fa[x]; 74 z = fa[y]; 75 } 76 return; 77 } 78 79 inline int getNbyV(int x) { 80 int p = root, ans; 81 while(1) { 82 ans = p; 83 if(val[p] == x) { 84 break; 85 } 86 if(val[p] > x && s[p][0]) { 87 p = s[p][0]; 88 } 89 else if(val[p] < x && s[p][1]) { 90 p = s[p][1]; 91 } 92 else { 93 break; 94 } 95 } 96 splay(ans, 0); 97 return ans; 98 } 99 100 inline int getpre() { 101 int p = s[root][0]; 102 while(s[p][1]) { 103 p = s[p][1]; 104 } 105 return p; 106 } 107 108 inline int getnex() { 109 int p = s[root][1]; 110 while(s[p][0]) { 111 p = s[p][0]; 112 } 113 return p; 114 } 115 116 inline int newNode(int x, int f) { 117 ++tot; 118 cnt[tot] = siz[tot] = 1; 119 val[tot] = x; 120 fa[tot] = f; 121 return tot; 122 } 123 124 inline void insert(int x) { 125 int p = root; 126 while(1) { 127 siz[p]++; 128 if(val[p] == x) { 129 cnt[p]++; 130 break; 131 } 132 if(x < val[p] && s[p][0]) { 133 p = s[p][0]; 134 } 135 else if(val[p] < x && s[p][1]) { 136 p = s[p][1]; 137 } 138 else { 139 bool f = (val[p] < x); 140 s[p][f] = newNode(x, p); 141 p = s[p][f]; 142 break; 143 } 144 } 145 splay(p, 0); 146 return; 147 } 148 void insert(int x, int p) { 149 if(val[p] == x) { 150 cnt[p]++; 151 } 152 else if(x < val[p] && s[p][0]) { 153 insert(x, s[p][0]); 154 } 155 else if(x > val[p] && s[p][1]) { 156 insert(x, s[p][1]); 157 } 158 else { 159 bool f = (val[p] < x); 160 s[p][f] = newNode(x, p); 161 } 162 pushup(p); 163 return; 164 } 165 166 inline void del(int x) { 167 int p = getNbyV(x); 168 if(cnt[p] > 1) { 169 cnt[p]--; 170 return; 171 } 172 int t = getpre(); 173 splay(t, root); 174 p = s[root][1]; 175 176 fa[p] = t; 177 s[t][1] = p; 178 fa[t] = 0; 179 root = t; 180 181 pushup(t); 182 return; 183 } 184 185 inline int getRbyV(int x) { 186 int p = getNbyV(x); 187 return siz[s[p][0]] + 1; 188 } 189 190 inline int getVbyR(int x) { 191 int p = root, t; 192 while(1) { 193 t = siz[s[p][0]]; 194 if(t >= x) { 195 p = s[p][0]; 196 } 197 else if(t + cnt[p] >= x) { 198 break; 199 } 200 else { 201 x -= (t + cnt[p]); 202 p = s[p][1]; 203 } 204 } 205 return val[p]; 206 } 207 208 inline int getXpre(int x) { 209 int p = getNbyV(x); 210 if(val[p] >= x) { 211 p = getpre(); 212 splay(p, 0); 213 } 214 return val[p]; 215 } 216 217 inline int getXnex(int x) { 218 int p = getNbyV(x); 219 if(val[p] <= x) { 220 p = getnex(); 221 splay(p, 0); 222 } 223 return val[p]; 224 } 225 226 void out(int p) { 227 if(s[p][0]) { 228 out(s[p][0]); 229 } 230 printf("%d ", val[p]); 231 if(s[p][1]) { 232 out(s[p][1]); 233 } 234 return; 235 } 236 237 }spt; 238 239 int main() { 240 int n; 241 scanf("%d", &n); 242 for(int i = 1, f, x; i <= n; i++) { 243 scanf("%d%d", &f, &x); 244 if(f == 1) { 245 spt.insert(x, spt.root); 246 //ot; 247 } 248 else if(f == 2) { 249 spt.del(x); 250 //ot; 251 } 252 else if(f == 3) { 253 printf("%d\n", spt.getRbyV(x) - 1); 254 } 255 else if(f == 4) { 256 printf("%d\n", spt.getVbyR(x + 1)); 257 } 258 else if(f == 5) { 259 printf("%d\n", spt.getXpre(x)); 260 } 261 else if(f == 6) { 262 printf("%d\n", spt.getXnex(x)); 263 } 264 else { 265 spt.clear(); 266 //ot; 267 } 268 } 269 return 0; 270 }
[update20181025]发现我的代码中有个问题,在rotate的时候可能会把fa[0]赋值为y,但是并不影响什么.....
接下来是序列版splay,也就是重头戏:序列之王!
因为splay的中序遍历单调递增,我们可以据此维护下标。
但是我们并不维护真正的下标,只是维护它们的顺序!
这样就能够支持区间翻转,最值,插入,删除,修改了。
和数版splay稍有变化。
写的时候发现了一点小问题:
两个区间最值好像不能同时维护...
因为两个哨兵会让两个区间最值冲突而炸掉。
不知道有没有什么解决办法...
结果我就分开写了......
1 #include <cstdio> 2 #include <algorithm> 3 const int N = 100010; 4 5 struct SplayTree { 6 int fa[N], s[N][2], siz[N], val[N], rev[N]; 7 int tot, root, ad[N]; 8 9 inline void pushup(int p) { 10 siz[p] = siz[s[p][0]] + siz[s[p][1]] + 1; 11 return; 12 } 13 14 inline void pushdown(int p) { 15 if(!rev[p]) { 16 return; 17 } 18 int ls = s[p][0], rs = s[p][1]; 19 if(ls) { 20 rev[ls] ^= 1; 21 } 22 if(rs) { 23 rev[rs] ^= 1; 24 } 25 std::swap(s[p][0], s[p][1]); 26 rev[p] = 0; 27 return; 28 } 29 30 int build(int l, int r, int f) { 31 int mid = (l + r) >> 1; 32 int p = ++tot; 33 val[p] = ad[mid]; 34 fa[p] = f; 35 if(l < mid) { 36 s[p][0] = build(l, mid - 1, p); 37 } 38 if(mid < r) { 39 s[p][1] = build(mid + 1, r, p); 40 } 41 pushup(p); 42 return p; 43 } 44 45 inline void init() { 46 root = 1; 47 tot = 2; /// space 48 fa[2] = 1; 49 s[1][1] = 2; 50 siz[2] = 1; 51 siz[1] = 2; 52 return; 53 } 54 55 SplayTree() { 56 init(); 57 } 58 59 inline void clear() { 60 for(int i = 3; i <= tot; i++) { 61 fa[i] = siz[i] = val[i] 62 = s[i][0] = s[i][1] = rev[i] = 0; 63 } 64 tot = 2; 65 root = 1; 66 return; 67 } 68 69 inline void rotate(int x) { 70 int y = fa[x]; 71 int z = fa[y]; 72 pushdown(y); 73 pushdown(x); 74 bool f = (s[y][1] == x); 75 76 if(z) { 77 s[z][s[z][1] == y] = x; 78 } 79 fa[x] = z; 80 s[y][f] = s[x][!f]; 81 fa[s[x][!f]] = y; 82 fa[y] = x; 83 s[x][!f] = y; 84 85 pushup(y); 86 pushup(x); 87 if(!z) { 88 root = x; 89 } 90 return; 91 } 92 93 inline void splay(int x, int g) { 94 int y = fa[x]; 95 int z = fa[y]; 96 while(y != g) { 97 if(z != g) { 98 (s[z][1] == y) ^ (s[y][1] == x) 99 ? rotate(x) : rotate(y); 100 } 101 rotate(x); 102 y = fa[x]; 103 z = fa[y]; 104 } 105 return; 106 } 107 108 inline int getNbyR(int x) { 109 int p = root, t; 110 while(1) { 111 pushdown(p); 112 t = siz[s[p][0]]; 113 if(t + 1 == x) { 114 break; 115 } 116 else if(t + 1 > x) { 117 p = s[p][0]; 118 } 119 else { 120 x -= (t + 1); 121 p = s[p][1]; 122 } 123 } 124 return p; 125 } 126 127 inline int get(int l, int r) { 128 r += 2; 129 int p = getNbyR(l); 130 splay(p, 0); 131 p = getNbyR(r); 132 splay(p, root); 133 return p; 134 } 135 136 inline void reverse(int l, int r) { 137 int p = get(l, r); 138 p = s[p][0]; 139 rev[p] ^= 1; 140 return; 141 } 142 143 void out(int p) { 144 pushdown(p); 145 if(s[p][0]) { 146 out(s[p][0]); 147 } 148 if(val[p]) { 149 printf("%d ", val[p]); 150 } 151 if(s[p][1]) { 152 out(s[p][1]); 153 } 154 return; 155 } 156 157 inline void insert(int l, int n) { 158 int p = get(l, l + 1); 159 s[p][1] = build(1, n, p); 160 pushup(p); 161 pushup(root); 162 return; 163 } 164 165 inline void del(int l, int r) { 166 int p = get(l, r); 167 s[p][0] = 0; 168 pushup(p); 169 pushup(root); 170 return; 171 } 172 173 }spt; 174 175 int main() { 176 int m, n; 177 scanf("%d%d", &n, &m); 178 for(int i = 1; i <= n; i++) { 179 spt.ad[i] = i; 180 } 181 spt.s[2][0] = spt.build(1, n, 2); 182 for(int i = 1, x, y; i <= m; i++) { 183 scanf("%d%d", &x, &y); 184 spt.reverse(x, y); 185 } 186 spt.out(spt.root); 187 return 0; 188 }
(这个模板写的有点乱...)
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 1000010, INF = 0x7f7f7f7f; 5 6 inline void Read(int &x) { 7 x = 0; 8 char c = getchar(); 9 while(c < '0' || c > '9') { 10 c = getchar(); 11 } 12 while(c >= '0' && c <= '9') { 13 x = (x << 3) + (x << 1) + c - 48; 14 c = getchar(); 15 } 16 return; 17 } 18 19 struct SplayTree { 20 int fa[N], s[N][2], siz[N]; 21 int val[N], small[N]; 22 int tot, root; 23 24 SplayTree() { 25 root = 1; 26 tot = 2; 27 28 val[1] = val[2] = INF; 29 fa[2] = 1; 30 s[1][1] = 2; 31 siz[1] = 2; 32 siz[2] = 1; 33 small[1] = small[2] = INF; 34 } 35 36 inline void pushup(int p) { 37 int ls = s[p][0]; 38 int rs = s[p][1]; 39 siz[p] = siz[ls] + siz[rs] + 1; 40 small[p] = val[p]; 41 if(ls) { 42 small[p] = std::min(small[p], small[ls]); 43 } 44 if(rs) { 45 small[p] = std::min(small[p], small[rs]); 46 } 47 return; 48 } 49 50 int build(int l, int r, int f) { 51 int mid = (l + r) >> 1; 52 int p = ++tot; 53 54 if(l < mid) { 55 s[p][0] = build(l, mid - 1, p); 56 } 57 Read(val[p]); 58 fa[p] = f; 59 if(mid < r) { 60 s[p][1] = build(mid + 1, r, p); 61 } 62 63 pushup(p); 64 return p; 65 } 66 67 inline void rotate(int x) { 68 int y = fa[x]; 69 int z = fa[y]; 70 bool f = (s[y][1] == x); 71 72 if(z) { 73 s[z][s[z][1] == y] = x; 74 } 75 fa[x] = z; 76 s[y][f] = s[x][!f]; 77 fa[s[x][!f]] = y; 78 fa[y] = x; 79 s[x][!f] = y; 80 81 pushup(y); 82 pushup(x); 83 if(!z) { 84 root = x; 85 } 86 return; 87 } 88 89 inline void splay(int x, int g) { 90 int y = fa[x]; 91 int z = fa[y]; 92 while(y != g){ 93 if(z != g) { 94 (s[z][1] == y) ^ (s[y][1] == x) 95 ? rotate(x) : rotate(y); 96 } 97 rotate(x); 98 y = fa[x]; /// space 99 z = fa[y]; 100 } 101 return; 102 } 103 104 inline int getNbyR(int x) { 105 int p = root, t; 106 while(1) { 107 t = siz[s[p][0]]; 108 if(t + 1 == x) { 109 break; 110 } 111 if(t + 1 > x){ 112 p = s[p][0]; 113 } 114 else if(t + 1 < x) { 115 x -= (t + 1); 116 p = s[p][1]; 117 } 118 } 119 return p; 120 } 121 122 inline int get(int l, int r) { 123 r += 2; 124 int p = getNbyR(l); 125 splay(p, 0); 126 p = getNbyR(r); 127 splay(p, root); 128 return s[p][0]; 129 } 130 131 inline int getmax(int l, int r) { 132 int p = get(l, r); 133 return small[p]; 134 } 135 136 void out(int p) { 137 if(s[p][0]) { 138 out(s[p][0]); 139 } 140 printf("%d ", val[p]); 141 if(s[p][1]) { 142 out(s[p][1]); 143 } 144 return; 145 } 146 }spt; 147 148 int main() { 149 int n, m; 150 scanf("%d%d", &n, &m); 151 spt.s[2][0] = spt.build(1, n, 2); 152 spt.pushup(2); 153 spt.pushup(1); 154 for(int i = 1, x, y; i <= m; i++) { 155 scanf("%d%d", &x, &y); 156 printf("%d ", spt.getmax(x, y)); 157 } 158 return 0; 159 }
1 #include <cstdio> 2 #define db printf("*") 3 typedef long long LL; 4 const int N = 100010; 5 6 struct SplayTree { 7 int fa[N], s[N][2], siz[N], tot, root; 8 LL val[N], delta[N], sum[N]; 9 SplayTree() { 10 tot = 2; 11 fa[2] = 1; 12 s[1][1] = 2; 13 root = 1; 14 } 15 16 inline void pushup(int p) { 17 siz[p] = siz[s[p][0]] + siz[s[p][1]] + 1; 18 sum[p] = sum[s[p][0]] + sum[s[p][1]] + val[p]; 19 return; 20 } 21 inline void pushdown(int p) { 22 if(!delta[p]) { 23 return; 24 } 25 int d = delta[p]; 26 int ls = s[p][0], rs = s[p][1]; 27 28 delta[ls] += d; 29 delta[rs] += d; 30 sum[ls] += d * siz[ls]; 31 sum[rs] += d * siz[rs]; 32 val[ls] += d; 33 val[rs] += d; 34 35 delta[p] = 0; 36 return; 37 } 38 39 int build(int l, int r, int f) { 40 int p = ++tot; 41 fa[p] = f; 42 int mid = (l + r) >> 1; 43 if(l < mid) { 44 s[p][0] = build(l, mid - 1, p); 45 } 46 scanf("%lld", &val[p]); 47 if(mid < r) { 48 s[p][1] = build(mid + 1, r, p); 49 } 50 pushup(p); 51 return p; 52 } 53 54 inline void rotate(int x) { 55 int y = fa[x]; 56 int z = fa[y]; 57 pushdown(y); 58 pushdown(x); 59 bool f = s[y][1] == x; 60 61 if(z) { 62 s[z][s[z][1] == y] = x; 63 } 64 fa[x] = z; 65 s[y][f] = s[x][!f]; 66 fa[s[x][!f]] = y; 67 fa[y] = x; 68 s[x][!f] = y; 69 70 if(!z) { 71 root = x; 72 } 73 pushup(y); 74 pushup(x); 75 return; 76 } 77 inline void splay(int x, int g) { 78 int y = fa[x]; 79 int z = fa[y]; 80 while(y != g) { 81 if(z != g) { 82 (s[y][1] == x) ^ (s[z][1] == y) ? 83 rotate(x) : rotate(y); 84 } 85 rotate(x); 86 y = fa[x]; /// !!! ERROR 87 z = fa[y]; 88 } 89 return; 90 } 91 92 int getNbyR(int x) { 93 int p = root; 94 while(1) { 95 int t = siz[s[p][0]]; 96 if(t >= x) { 97 p = s[p][0]; 98 } 99 else if(t + 1 == x) { 100 break; 101 } 102 else { 103 x -= (t + 1); 104 p = s[p][1]; 105 } 106 } 107 return p; 108 } 109 inline int get(int l, int r) { 110 int p = getNbyR(l); 111 splay(p, 0); 112 p = getNbyR(r + 2); 113 splay(p, root); 114 return p; 115 } 116 117 inline void add(int l, int r, LL v) { 118 int p = get(l, r); 119 p = s[p][0]; 120 sum[p] += v * siz[p]; 121 val[p] += v; 122 delta[p] += v; 123 return; 124 } 125 126 inline LL asksum(int l, int r) { 127 int p = get(l, r); 128 return sum[s[p][0]]; 129 } 130 }spt; 131 132 int main() { 133 int n, m; 134 scanf("%d%d", &n, &m); 135 spt.s[2][0] = spt.build(1, n, 2); 136 spt.pushup(2); 137 spt.pushup(1); 138 139 int f, x, y, z; 140 while(m--) { 141 scanf("%d", &f); 142 if(f == 1) { 143 scanf("%d%d%d", &x, &y, &z); 144 spt.add(x, y, z); 145 } 146 else { 147 scanf("%d%d", &x, &y); 148 printf("%lld\n", spt.asksum(x, y)); 149 } 150 } 151 152 return 0; 153 }
接下来是一些例题:
(此处应有例题)
朝鲜树/替罪羊树:
不维护,基于重构。
当这棵树不平衡到一定程度之后就扔了,重新建一个完全二叉树。
Treap:
Tree + Heap,基于随机。
给每个节点放一个随机的dat值,要使val满足BST性质的同时dat满足堆性质。
SBT:
Size Balanced Tree。由于有maintain它十分的平衡。
红黑树:
效率极高,代码极难,c++模板用树。
AVl:
???
... ...