Splay模板

此模板对于信息竞赛已经够用了,但是没有考虑建两棵或以上的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最近正在实现,因为一些特殊的原因没能在今天完成有点可惜

大概明天就可以搞好,会发上来的

实在是很累,先休息一晚上吧……到时候再推荐一下平衡树的入门题好了

很可惜,身边的所有人都告诉我要以学业为重,这个博客可能无法持续更新

真的,我觉得自己曾经的梦想幻灭,心很痛。

posted @ 2015-03-14 20:03  JohnsonYip  阅读(105)  评论(0编辑  收藏  举报