【模板】普通平衡树

题面

题解

过年啦!!!

在这红红火火的日子里,肯定要写\(\color{red}{\mathrm{Red}}\;\color{black}{\mathrm{Black}}\;tree\)来愉悦身心啊

然鹅出现了一些小尴尬

虽然代码行数跟\(\mathrm{s(p)lay}\)没法比肯定是大括号太占地方了

但是:

指针版的\(\mathrm{s(p)lay}\)https://www.luogu.org/recordnew/show/8772600

\(\color{red}{\mathrm{Red}}\;\color{black}{\mathrm{Black}}\;tree\)https://www.luogu.org/recordnew/show/16079271

代码长度比较起来,红黑树胜!!!

ha???

速度当然也是吊着打啦

从此红黑树走进了每个OIer的电脑

代码

我这能算突破红黑树代码长度极限了吗\(\mathrm{QwQ}\)

#include<cstdio>
#include<cstring>
#include<climits>
#define RG register

inline int read()
{
	int data = 0, w = 1;
	char ch = getchar();
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(1e6 + 10);
int son[2][maxn], fa[maxn], size[maxn], cur;
int cnt[maxn], col[maxn], val[maxn], root;
inline void newNode(int k, int c, int f)
{
	int x = ++cur;
	fa[x] = f, size[x] = cnt[x] = 1;
	val[x] = k, col[x] = c;
}

inline void update(int x) { size[x] = size[son[0][x]] + cnt[x] + size[son[1][x]]; }
inline void rotate(int x, int r)
{
	int y = son[!r][x]; son[!r][x] = son[r][y];
	if(son[r][y]) fa[son[r][y]] = x;
	fa[y] = fa[x]; if(!fa[x]) root = y;
	else son[x == son[1][fa[x]]][fa[x]] = y;
	son[r][y] = x, fa[x] = y, size[y] = size[x];
	update(x);
}

inline void transplant(int to, int from)
{
	fa[from] = fa[to]; if(!fa[to]) root = from;
	else son[to == son[1][fa[to]]][fa[to]] = from;
}

int findMin(int x) { while(son[0][x]) x = son[0][x]; return x; }
void insertFixUp(int z)
{
	while(col[fa[z]])
	{
		int f = fa[z], g = fa[f], l = f == son[0][g], y = son[l][g];
		if(col[y]) col[y] = col[f] = 0, col[z = g] = 1;
		else
		{
			if(z == son[l][f]) z = f, rotate(z, !l);
			col[fa[z]] = 0, col[fa[fa[z]]] = 1; rotate(g, l);
		}
	}
	col[root] = 0;
}

void insert(int k)
{
	int x = root, y = 0;
	while(x)
	{
		++size[y = x]; if(val[x] == k) return (void) (++cnt[x]);
		x = son[val[x] < k][x];
	}
	newNode(k, 1, y);
	if(!y) root = cur; else son[val[y] < k][y] = cur;
	insertFixUp(cur);
}

void delFixUp(int x)
{
	while(x != root && (!col[x]))
	{
		int l = x == son[0][fa[x]], f = fa[x], w = son[l][f];
		if(col[w])
		{
			col[f] = 1, col[w] = 0;
			rotate(f, !l); w = son[l][f];
		}
		if((!col[son[0][w]]) && (!col[son[1][w]])) col[w] = 0, x = fa[x];
		else
		{
			if(!col[son[l][w]])
				col[w] = 1, col[son[!l][w]] = 0,
				rotate(w, l), w = son[l][f];
			col[w] = col[f], col[f] = 0; col[son[l][w]] = 0;
			rotate(fa[w], !l); x = root;
		}
	}
	col[x] = 0;
}

void erase(int k)
{
	int z = root, w = 0;
	while(z)
	{
		--size[w = z]; if(k == val[z]) break;
		z = son[val[z] < k][z];
	}
	if(z)
	{
		if(cnt[z] > 1) return (void) (--cnt[z]);
		int y = z, x, oldc = col[y];
		if(!son[0][z]) x = son[1][z], transplant(z, son[1][z]);
		else if(!son[1][z]) x = son[0][z], transplant(z, son[0][z]);
		else
		{
			y = findMin(son[1][z]); oldc = col[y], x = son[1][y];
			if(fa[y] == z) fa[x] = y;
			else
			{
				int tmpy = y;
				while(tmpy != z) size[tmpy] -= cnt[y], tmpy = fa[tmpy];
				transplant(y, son[1][y]); son[1][y] = son[1][z];
				fa[son[1][y]] = y;
			}
			transplant(z, y); son[0][y] = son[0][z];
			fa[son[0][y]] = y, col[y] = col[z]; update(y);
		}
		if(!oldc) delFixUp(x);
	}
	else while(w) ++size[w], w = fa[w];
}

inline int cmp(int x, int k) { return (val[x] < k) ? 0 : (val[x] ^ k ? 1 : -1); }
int suc(int k, int b)
{
	int x = root, p = 0;
	while(x) if(cmp(x, k) == b) p = x, x = son[!b][x];
	else x = son[b][x];
	return val[p];
}

int k_th(int k)
{
	int x = root;
	while(x)
	{
		int l = son[0][x], r = son[1][x];
		if(size[l] + 1 <= k && size[l] + cnt[x] >= k) return val[x];
		else if(size[l] + cnt[x] < k) k -= size[l] + cnt[x], x = r; else x = l;
	}
	return INT_MAX;
}

inline int rank(int r)
{
	int x = root, ret = 0;
	while(x)
	{
		if(val[x] < r) ret += size[son[0][x]] + cnt[x], x = son[1][x];
		else x = son[0][x];
	}
	return ret + 1;
}

int main()
{
	int n = read();
	while(n--)
	{
		int opt = read(), x = read();
		switch(opt)
		{
			case 1: insert(x); break;
			case 2: erase(x); break;
			case 3: printf("%d\n", rank(x)); break;
			case 4: printf("%d\n", k_th(x)); break;
			case 5: case 6: printf("%d\n", suc(x, opt - 5)); break;
		}
	}
	return 0;
}
posted @ 2019-02-06 15:32  xgzc  阅读(175)  评论(2编辑  收藏  举报