平衡树汇总
一.Treap
#include <bits/stdc++.h> using namespace std; const int SIZE = 100010; int INF = 0x7fffffff; int m, opt, x; int tot, root, n; struct Treap { int l, r; int val, dat; int cnt, size; }a[SIZE]; int New(int val) { a[++tot].val = val; a[tot].dat = rand(); a[tot].cnt = a[tot].size = 1; return tot; } void updata(int cur) { a[cur].size = a[a[cur].l].size + a[a[cur].r].size + a[cur].cnt; } void build() { New(-INF), New(INF); root = 1; a[1].r = 2; updata(root); } int GetRankByVal(int p, int val) { if(p == 0) return 0; if(val == a[p].val) return a[a[p].l].size + 1; if(val < a[p].val) return GetRankByVal(a[p].l, val); return GetRankByVal(a[p].r, val) + a[a[p].l].size + a[p].cnt; } int GetValByRank(int p, int rank) { if(p == 0) return INF; if(a[a[p].l].size >= rank) return GetValByRank(a[p].l, rank); if(a[a[p].l].size + a[p].cnt >= rank) return a[p].val ; return GetValByRank(a[p].r, rank - a[a[p].l].size - a[p].cnt); } void zig(int &p) { int q = a[p].l; a[p].l = a[q].r; a[q].r = p; p = q; updata(a[p].r), updata(p); } void zag(int &p) { int q = a[p].r; a[p].r = a[q].l; a[q].l = p; p = q; updata(a[p].l), updata(p); } void Insert(int &p, int val) { if(p == 0) { p = New(val); return; } if(val == a[p].val) { a[p].cnt++; updata(p); return; } if(val < a[p].val) { Insert(a[p].l, val); if(a[p].dat < a[a[p].l].dat) zig(p); } else { Insert(a[p].r, val); if(a[p].dat < a[a[p].r].dat) zag(p); } updata(p); } int GetPre(int val) { int ans = 1; int p = root; while(p) { if(val == a[p].val) { if(a[p].l > 0) { p = a[p].l; while(a[p].r > 0) p = a[p].r; ans = p; } break; } if(a[p].val < val && a[p].val > a[ans].val) ans = p; p = val < a[p].val ? a[p].l : a[p].r; } return a[ans].val; } int GetNext(int val) { int ans = 2; int p = root; while(p) { if(val == a[p].val) { if(a[p].r > 0) { p = a[p].r; while(a[p].l > 0) p = a[p].l; ans = p; } break; } if(a[p].val > val && a[p].val < a[ans].val) ans = p; p = val < a[p].val ? a[p].l : a[p].r; } return a[ans].val; } void Remove(int &p, int val) { if(p == 0)return; if(val == a[p].val) { if(a[p].cnt > 1) { a[p].cnt--; updata(p); return; } if(a[p].l || a[p].r) { if(a[p].r == 0 || a[a[p].l].dat > a[a[p].r].dat) { zig(p); Remove(a[p].r, val); } else { zag(p); Remove(a[p].l, val); } updata(p); } else p = 0; return; } val < a[p].val ? Remove(a[p].l, val) : Remove(a[p].r, val); updata(p); } int main() { srand(time(0)); build(); cin>>m; while(m--) { scanf("%d%d",&opt,&x); switch(opt) { case 1: Insert(root, x); break; case 2: Remove(root, x); break; case 3: printf("%d\n",GetRankByVal(root, x) - 1); break; case 4: printf("%d\n",GetValByRank(root, x + 1)); break; case 5: printf("%d\n",GetPre(x)); break; case 6: printf("%d\n",GetNext(x)); break; } } return 0; }
二.Splay
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 10000010 #define inf 0x7f7f7f7f struct SplayTree { int ch[2], fa; int val, siz; int cnt;// 副本数 }t[maxn]; int Root, tot; void pushup(int o) { t[o].siz = t[t[o].ch[0]].siz + t[t[o].ch[1]].siz + t[o].cnt; } void rotate(int x) { int y = t[x].fa, d = (t[y].ch[1] == x); t[ t[y].ch[d] = t[x].ch[d ^ 1] ].fa = y; // x 的儿子给 y ; t[ t[x].fa = t[y].fa ].ch[ t[t[y].fa].ch[1] == y ] = x; // x 归为 y 的父亲的儿子 ; t[ t[x].ch[d ^ 1] = y ].fa = x; // y 归为 x 的儿子; pushup(y), pushup(x); } void Splay(int x, int f) // 把 x 旋转成 f 的儿子, 如果 f = 0, x 旋转到根节点: { while(t[x].fa != f) { int y = t[x].fa, z = t[y].fa; if(z != f) { if ((t[z].ch[0] == y) == (t[y].ch[0] == x)) { rotate(y); } else { rotate(x); } //rotate( (t[z].ch[0] == y) == (t[y].ch[0] == x) ? y : x);// x 与 y 为同一边子树 旋转 y, 否则旋转 x; } rotate(x); } pushup(x); if(f == 0) Root = x; } void insert(int v) { int o = Root, u = 0; while(o && t[o].val != v) { u = o; int d = t[o].val < v; o = t[o].ch[d]; } if(o) { t[o].cnt ++; pushup(o); } else { o = ++tot; if (u) { int d = t[u].val < v; t[u].ch[d] = o; } t[o].fa = u; t[o].val = v;//cout<<t[o].val<<endl; t[o].siz = 1; t[o].cnt = 1; t[o].ch[1] = t[o].ch[0] = 0; } Splay(o, 0); } int K_th(int k) { int o = Root; if(t[o].siz < k) { return 0; } while(1) { if(k > t[t[o].ch[0]].siz + t[o].cnt) { k -= t[t[o].ch[0]].siz + t[o].cnt; o = t[o].ch[1]; } else if(t[t[o].ch[0]].siz >= k) { o = t[o].ch[0]; } else { break; } } Splay(o, 0); return t[o].val; } void Find(int x) { int o = Root; if(!o) return ; /* while(1) { if(t[o].val == x) { Splay(o, 0); return ; } int d = t[o].val < x; if(!t[o].ch[o]) return ; o = t[o].ch[o]; }*/ while(t[o].ch[t[o].val < x] and x != t[o].val) { o = t[o].ch[t[o].val < x]; } Splay(o, 0); } int Next(int x, int d) { Find(x); int o = Root; if( (t[o].val > x and d) or (t[o].val < x and !d)) return o; o = t[o].ch[d]; while(t[o].ch[d ^ 1]) o = t[o].ch[d ^ 1]; return o; } void Del(int x) { int lst = Next(x, 0); int nxt = Next(x, 1); Splay(lst, 0);Splay(nxt, lst); int del = t[nxt].ch[0]; if(t[del].cnt > 1) { t[del].cnt --; Splay(del, 0); } else t[nxt].ch[0] = 0; } int main() { insert(inf); insert(-inf); int n; cin >> n; while(n--) { int opt, x; scanf("%d%d", &opt, &x); if(opt == 1) { insert(x); } else if(opt == 2) { Del(x); } else if(opt == 3) { Find(x); printf("%d\n", t[t[Root].ch[0]].siz); } else if(opt == 4) { printf("%d\n", K_th(x + 1)); } else if(opt == 5) { printf("%d\n", t[Next(x, 0)].val); } else { printf("%d\n", t[Next(x, 1)].val); } } return 0; }
三.无旋Treap
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> using namespace std; #define maxn 500005 struct FHQ_Treap { int ch[2]; int val, pri; int siz, cnt; }t[maxn]; int tot, Root; int newnode(int v) { tot++; t[tot].ch[1] = t[tot].ch[2] = 0; t[tot].cnt = t[tot].siz = 1; t[tot].val = v; t[tot].pri = rand(); return tot; } void pushup(int o) { t[o].siz = t[t[o].ch[1]].siz + t[t[o].ch[0]].siz + t[o].cnt; } int Merge(int x, int y) { if(!x or !y) return x + y; if(t[x].pri < t[y].pri) { t[x].ch[1] = Merge(t[x].ch[1], y); pushup(x); return x; } else { t[y].ch[0] = Merge(x, t[y].ch[0]); pushup(y); return y; } } #define par pair<int, int> #define m_p make_pair #define fi first #define se second par Split1(int o, int k) // 按排名切 { if(!o or !k) return m_p(0, o); int d = t[t[o].ch[0]].siz; par res; if(k <= d) { res = Split1(t[o].ch[0], k); t[o].ch[0] = res.second; pushup(o); res.second = o; } else { res = Split1(t[o].ch[1], k - d - 1); t[o].ch[1] = res.first; pushup(o); res.first = o; } return res; } void Split2(int o, int k, int &x, int &y) // 按价值切 { if(!o) x = y = 0; else { if(t[o].val <= k) { x = o; Split2(t[o].ch[1], k, t[o].ch[1], y); } else { y = o; Split2(t[o].ch[0], k, x, t[o].ch[0]); } pushup(o); } } int K_th(int o, int k) { while(1) { if(k <= t[t[o].ch[0]].siz) { o = t[o].ch[0]; } else if(k == t[t[o].ch[0]].siz + t[o].cnt) { return o; } else { k -= t[t[o].ch[0]].siz + t[o].cnt; o = t[o].ch[1]; } } } int main() { srand(time(0)); int n; cin >> n; while(n--) { int opt, a; scanf("%d%d", &opt, &a); int x, y, z; if(opt == 1) { Split2(Root, a, x, y); Root = Merge(Merge(x, newnode(a)), y); } else if(opt == 2) { Split2(Root, a, x, z); Split2(x, a - 1, x, y); y = Merge(t[y].ch[0], t[y].ch[1]); Root = Merge(Merge(x, y), z); } else if(opt == 3) { Split2(Root, a - 1, x, y); printf("%d\n", t[x].siz + t[x].cnt); Root = Merge(x, y); } else if(opt == 4) { printf("%d\n", t[K_th(Root, a)].val); } else if(opt == 5) { Split2(Root, a - 1, x, y); printf("%d\n", t[K_th(x, t[x].siz)].val); Root = Merge(x, y); } else { Split2(Root, a, x, y); printf("%d\n", t[K_th(y, 1)].val); Root = Merge(x, y); } } return 0; }