【题目链接】
【思路要点】
- 本题包含了平衡树最基本的操作。是任何学习平衡树都应当先做一遍的题。
- 笔者实现了四种平衡树,Splay、Treap、替罪羊树和非旋转式Treap(以及其可持久化)。
【代码】
- Splay
/*Splay Tree Version*/ #include<bits/stdc++.h> using namespace std; #define MAXN 100005 template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } struct Splay { int root, total; int child[MAXN][2], father[MAXN]; int index[MAXN], size[MAXN], cnt[MAXN]; bool get(int x) { return x == child[father[x]][1]; } void update(int x) { size[x] = cnt[x]; size[x] += size[child[x][0]]; size[x] += size[child[x][1]]; } void rotate(int x) { int f = father[x], g = father[f]; if (f == 0) return; int tmp = get(x), tnp = get(f); child[f][tmp] = child[x][tmp ^ 1]; if (child[x][tmp ^ 1]) father[child[x][tmp ^ 1]] = f; child[x][tmp ^ 1] = f; father[f] = x; father[x] = g; if (g) child[g][tnp] = x; update(f); update(x); } void splay(int x) { for (int f = father[x]; (f = father[x]); rotate(x)) if (get(f) == get(x)) rotate(f); else rotate(x); root = x; } void insert(int x) { if (root == 0) { root = ++total; index[root] = x; cnt[root] = size[root] = 1; return; } int now = root; while (true) { if (x == index[now]) { cnt[now]++; splay(now); return; } bool tmp = index[now] < x; if (child[now][tmp]) now = child[now][tmp]; else { child[now][tmp] = ++total; father[total] = now; index[total] = x; cnt[total] = size[total] = 1; splay(total); return; } } } int rank(int x) { int now = root, ans = 1; while (true) { if (index[now] <= x) { ans += size[child[now][0]]; if (index[now] == x) { splay(now); return ans; } ans += cnt[now]; now = child[now][1]; } else now = child[now][0]; } } int pre() { int now = child[root][0]; while (child[now][1]) now = child[now][1]; return now; } int suc() { int now = child[root][1]; while (child[now][0]) now = child[now][0]; return now; } void del(int x) { rank(x); if (cnt[root] >= 2) { cnt[root]--; size[root]--; return; } if (child[root][0] == 0 && child[root][1] == 0) { root = 0; return; } if (child[root][0] == 0) { root = child[root][1]; father[root] = 0; return; } if (child[root][1] == 0) { root = child[root][0]; father[root] = 0; return; } splay(pre()); child[r