Splay求调(悬关)
查看原帖
Splay求调(悬关)
742157
ZYK_luogu楼主2023/12/15 20:07
#include <iostream>
#include <cstdio>

using namespace std;
const int N = 1e5+10;

int root = 0, idx = 0, val[N], cnt[N], son[N][2], siz[N], fa[N];

int get(int x) { return son[fa[x]][1] == x; }

void maintain(int x) { siz[x] = siz[son[x][0]] + siz[son[x][1]] + cnt[x]; }

void clear(int x) { siz[x] = son[x][0] = son[x][1] = val[x] = cnt[x] = fa[x] = 0; }

int newNode(int key, int ls = 0, int rs = 0)
{
	idx ++;
	val[idx] = key;
	cnt[idx] = 1;
	son[idx][0] = ls, son[idx][1] = rs;
	return idx;
}

void rotate(int x)
{
	int y = fa[x], z = fa[y], d = get(x);
	if(son[x][!d])
		fa[son[x][!d]] = y, son[y][d] = son[x][!d];
	if(z) fa[x] = z;
	son[x][!d] = y, fa[y] = x;
	maintain(y), maintain(x);
}

void splay(int x)
{
	if(root == x) return;

	for(int f = fa[x]; f; rotate(x))
	{
		if(f) rotate(get(f) == get(x) ? f : x);
		f = fa[x];
	}

	root = x;
}

void ins(int key)
{
	int cur = root, f = 0;

	if(!root)
	{
		root = newNode(key);
		maintain(root);
		splay(root);
		return;
	}

	while(true)
	{
		if(val[cur] == key)
		{
			cnt[cur] ++;
			maintain(cur), maintain(f);
			splay(cur);
			return;
		}
		
		f = cur, cur = son[cur][key > val[cur]];
		if(!cur)
		{
			son[f][key > val[f]] = newNode(key);
			maintain(idx);
			maintain(f);
			splay(cur);
		}
	}
}

void merge(int x, int y)
{
	int cur1 = x, cur2 = y;

	while(cur1 && son[cur1][1]) 
		cur1 = son[cur1][1];
	
	while(cur2 && son[cur2][1]) 
		cur2 = son[cur2][1];
	
	if(val[cur1] > val[cur2])
	{
		root = cur1;
		splay(cur1);
	}
	else
	{
		root = cur2;
		splay(cur2);
	}
}

void del(int key)
{
	int cur = root;
	while(val[cur] != key)
	{
		if(val[cur] > key)
		{
			if(!son[cur][0]) return;
			cur = son[cur][0];
		}
		else
		{
			if(!son[cur][1]) return;
			cur = son[cur][1];
		}
	}
	splay(cur);

	if(cnt[cur] > 1) 
	{
		cnt[cur] --;
		return;
	}
	merge(son[cur][0], son[cur][1]);
	clear(cur);
}

int get_rank_by_key(int key)
{
	int cur = root, res = 0;

	while(cur)
	{
		if(key < val[cur])
			cur = son[cur][0];
		else
		{
			res += siz[son[cur][0]];
			if(key == val[cur])
			{
				res += 1;
				return res;
			}
			res += cnt[cur];
			cur = son[cur][1];
		}
	}
	return res;
}

int get_key_by_rank(int rk)
{
	int cur = root;

	while(cur)
	{
		if(rk <= siz[son[cur][0]])
			cur = son[cur][0];
		else
		{
			rk -= (siz[son[cur][0]] + cnt[cur]);
			if(rk <= 0) return siz[son[cur][0]] + 1;
			cur = son[cur][1];
		}
	}
	return 0;
}

int get_prev(int x)
{
	ins(x);
	int cur = son[root][0];
	while(cur && son[cur][1])
		cur = son[cur][1];

	if(cur == 0) return 0;
	splay(cur);
	del(x);
	return val[cur];
}

int get_next(int x)
{
	ins(x);
	int cur = son[root][1];
	while(cur && son[cur][0])
		cur = son[cur][0];
	
	if(cur == 0) return 0;
	splay(cur);
	del(x);
	return val[cur];
}

void debug(int x)
{
	printf("debug : %d\n", x);
	if(!x) return;

	printf("Node %d : fa = %d, siz = %d, val = %d, cnt = %d, son = {%d, %d}\n", x, fa[x], siz[x], val[x], cnt[x], son[x][0], son[x][1]);

	debug(son[x][0]);
	debug(son[x][1]);
}

int main()
{
	int n, opt, x;
	scanf("%d", &n);

	while(n --)
	{
		scanf("%d%d", &opt, &x);

		if(opt == 1) ins(x);
		else if(opt == 2) del(x);
		else if(opt == 3) printf("%d\n", get_rank_by_key(x));
		else if(opt == 4) printf("%d\n", get_key_by_rank(x));
		else if(opt == 5) printf("%d\n", get_prev(x));
		else if(opt == 6) printf("%d\n", get_next(x));
		else debug(root), printf("root = %d, idx = %d\n", root, idx);
	}
	return 0;
}
2023/12/15 20:07
加载中...