此模板对于信息竞赛已经够用了,但是没有考虑建两棵或以上的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\n", rank(x)); break;
case 4: printf("%d\n", weight[find_kth(x)]); break;
case 5: printf("%d\n", weight[prev(x)]); break;
case 6: printf("%d\n", weight[succ(x)]); break;
}
}
return 0;
}
这其实是BZOJ3224 Tyvj1728 普通平衡树的题解
此题是极好的模板题,任何二叉搜索树都可以用它来检测代码的正确性
对了那个类的Splay最近正在实现,因为一些特殊的原因没能在今天完成有点可惜
大概明天就可以搞好,会发上来的
实在是很累,先休息一晚上吧……到时候再推荐一下平衡树的入门题好了
很可惜,身边的所有人都告诉我要以学业为重,这个博客可能无法持续更新
真的,我觉得自己曾经的梦想幻灭,心很痛。