此模板对于信息竞赛已经够用了,但是没有考虑建两棵或以上的Splay的情况,如果是需要实现可以稍微改一下
纪念一下曾经的Notonlysuccess,我从那里学会了线段树和splay,可惜现在好像上不去了……
这段代码作为模板也挺不错的,自我感觉可扩展性良好
#include <cstdio> #define MAXN 100010 using namespace std; int n; int root, node; int parent[MAXN], child[MAXN][2]; int weight[MAXN], size[MAXN], count[MAXN]; int trash[MAXN], top; inline void update(int x) { size[x] = count[x] + size[child[x][0]] + size[child[x][1]]; } inline void rotate(int x) { int y = parent[x]; bool dir = child[y][0] == x; if (child[y][!dir] = child[x][dir]) parent[child[x][dir]] = y; if (parent[x] = parent[y]) child[parent[y]][child[parent[y]][1] == y] = x; update(child[x][dir] = y); parent[y] = x; } inline void splay(int x, int goal) { for (int y = parent[x]; y ^ goal; rotate(x), y = parent[x]) if (parent[y] ^ goal) rotate(child[y][child[parent[y]][0] == y] ? x : y); update(x); if (!goal) root = x; } inline void new_node(int w, int &x, int pre) { if (top) x = trash[--top]; else x = ++node; child[x][0] = child[x][1] = 0; count[x] = size[x] = 1; parent[x] = pre; weight[x] = w; } inline void insert(int value) { int x = root; if (size[x]) { int y = parent[x]; while (x && value ^ weight[x]) ++size[x], y = x, x = child[x][value > weight[x]]; bool dir = value > weight[y]; if (x) ++size[x], ++count[x]; else new_node(value, child[y][dir], y); } else new_node(value, root, 0); } inline void remove(int value) { int x = root; while (x && value ^ weight[x]) x = child[x][value > weight[x]]; if (!x) return; if (count[x] == 1) { bool f = !child[x][0]; int y = child[x][f] ? child[x][f] : x; while (child[y][!f]) y = child[y][!f]; bool b = child[parent[y]][1] == y; if (parent[y]) child[parent[y]][b] = child[y][f]; if (child[y][f]) parent[child[y][f]] = parent[y]; weight[x] = weight[y]; count[x] = count[y]; for (count[x = y] = 0; x; x = parent[x]) update(x); if (root == (trash[top++] = y)) root = 0; } else for (--count[x]; x; x = parent[x]) --size[x]; } inline int search(int w) { int x = root; while (x && w ^ weight[x]) x = child[x][w > weight[x]]; splay(x, root); return x; } inline int rank(int w) { int x = root, ret = 0; while (x && w ^ weight[x]) if (w < weight[x]) x = child[x][0]; else ret += count[x] + size[child[x][0]], x = child[x][1]; return ret + size[child[x][0]] + 1; } inline int find_kth(int k) { if (k < 0 || k > size[root]) return 0; int x = root; while (k <= size[child[x][0]] || k > size[child[x][0]] + count[x]) if (k <= size[child[x][0]]) x = child[x][0]; else k -= size[child[x][0]] + count[x], x = child[x][1]; splay(x, 0); return x; } inline int prev(int w) { int x = root, y = 0; while (x) if (w <= weight[x]) x = child[x][0]; else y = x, x = child[x][1]; if (y) splay(y, 0); return y; } inline int succ(int w) { int x = root, y = 0; while (x) if (w >= weight[x]) x = child[x][1]; else y = x, x = child[x][0]; if (y) splay(y, 0); return y; } int main() { for (scanf("%d", &n); n; --n) { int op, x; scanf("%d%d", &op, &x); switch (op) { case 1: insert(x); break; case 2: remove(x); break; case 3: printf("%d ", rank(x)); break; case 4: printf("%d ", weight[find_kth(x)]); break; case 5: printf("%d ", weight[prev(x)]); break; case 6: printf("%d ", weight[succ(x)]); break; } } return 0; }
这其实是BZOJ3224 Tyvj1728 普通平衡树的题解
此题是极好的模板题,任何二叉搜索树都可以用它来检测代码的正确性
对了那个类的Splay最近正在实现,因为一些特殊的原因没能在今天完成有点可惜
大概明天就可以搞好,会发上来的
实在是很累,先休息一晚上吧……到时候再推荐一下平衡树的入门题好了
很可惜,身边的所有人都告诉我要以学业为重,这个博客可能无法持续更新
真的,我觉得自己曾经的梦想幻灭,心很痛。