P3369 【模板】普通平衡树

原题链接
代码如下:

#include <bits/stdc++.h>

using namespace std;

inline int read() {
	int x = 0, f = 0; char ch = getchar();
	while (!isdigit(ch)) f = ch == '-', ch = getchar();
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}

struct Node {
	int son[2], fa, cnt, siz, v;
}; 
const int N = 1e5 + 10, inf = 1e9; 
int n, rt, tot; 
Node nd[N]; 

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

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

void connect(int x, int fa, int t) {
	if (fa) nd[fa].son[t] = x;
	nd[x].fa = fa;  
}

void rotate(int x) {
	int f = nd[x].fa, ff = nd[f].fa, t = get(x), tf = get(f), b = nd[x].son[t ^ 1]; 
	connect(x, ff, tf); connect(f, x, t ^ 1); connect(b, f, t); 
	update(f); update(x); 
}

void splay(int x, int u) {
//	printf("splay(%d, %d)\n", x, u); 
	for (int f = nd[x].fa; f != u; f = nd[x].fa) {
		if (nd[f].fa != u) {
			rotate(get(f) == get(x) ? f : x);  
		}
		rotate(x);  
	}
	if (!u) rt = x; 
}

void insert(int x) {
	int u = rt, f = 0; 
	while (u && x != nd[u].v) {
		f = u; u = nd[u].son[x > nd[u].v]; 
	}
	if (u) {
		++nd[u].cnt; ++nd[u].siz; 
	} else {
		u = ++tot; 
		if (f) nd[tot].fa = f, nd[f].son[x > nd[f].v] = tot; 
		nd[tot].cnt = nd[tot].siz = 1; 
		nd[tot].v = x; 
	}
	splay(u, 0); 
}

void find(int x) {
	int u = rt; 
	while (nd[u].v != x && nd[u].son[x > nd[u].v]) {
		u = nd[u].son[x > nd[u].v]; 
	}
	splay(u, 0); 
} 

int nex(int x, int f) {
	find(x); 
	if ((nd[rt].v < x && !f) || (nd[rt].v > x && f)) return rt; 
	int u = nd[rt].son[f]; 
	while (nd[u].son[f ^ 1]) u = nd[u].son[f ^ 1]; 
	return u; 
}

void del(int x) {
	int u = nex(x, 0), v = nex(x, 1); 
	splay(u, 0); splay(v, u); 
	int b = nd[v].son[0]; 
	if (nd[b].cnt > 1) {
		--nd[b].cnt, splay(b, 0); 
	} else {
		nd[b].cnt = nd[b].siz = nd[b].v = nd[b].fa = 0;
		nd[v].son[0] = 0; 
	}
}

int kth(int x) {
	int u = rt, k = x;
	while (u) {
		if (k <= nd[nd[u].son[0]].siz) {
			u = nd[u].son[0]; 
		} else if (k > nd[nd[u].son[0]].siz + nd[u].cnt) {
			k -= nd[nd[u].son[0]].siz + nd[u].cnt; u = nd[u].son[1]; 
		} else break; 
	} 
	return nd[u].v; 
}

int main() {
	insert(inf); insert(-inf); 
	n = read(); 
	for (int i = 1; i <= n; ++i) {
		int opt = read(), x = read(); 
		if (opt == 1) insert(x); 
		else if (opt == 2) del(x); 
		else if (opt == 3)  {
			find(x); 
			printf("%d\n", nd[nd[rt].son[0]].siz); 
		} else if (opt == 4) printf("%d\n", kth(x + 1));
		else if (opt == 5) printf("%d\n", nd[nex(x, 0)].v); 
		else printf("%d\n", nd[nex(x, 1)].v); 
	}
	return 0; 
}

/*
rotate操作
节点编号与值混淆
nex特判 
del后需要splay 
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值