蒟蒻求调 Splay 93pts
查看原帖
蒟蒻求调 Splay 93pts
523585
silent_ST楼主2024/7/16 18:03

rt

//模板:Splay树 伸展树
//题目:P3369 【模板】普通平衡树
#include <iostream>
using namespace std;
#define ls(x) tr[x].s[0]
#define rs(x) tr[x].s[1]
const int maxn = 1e7 + 5;
struct node {
	int s[2], val, cnt, siz, fa;
	//左右儿子,值,出现次数,子树大小,父节点编号
	void init(int p, int v) {
		fa = p;
		val = v;
		cnt = siz = 1;
	}
} tr[maxn];
long long root, idx = 0, n;

//上传
void pushup(int x) {
	tr[x].siz = tr[ls(x)].siz + tr[rs(x)].siz + tr[x].cnt;
}
//旋转
void rotate(int now) {
	int y = tr[now].fa, z = tr[y].fa;
	int k = (rs(y) == now);//k = 0  k = 1
	tr[y].s[k] = tr[now].s[k ^ 1];

	tr[tr[now].s[k ^ 1]].fa = y;
	tr[now].s[k ^ 1] = y;

	tr[y].fa = now;
	tr[z].s[rs(z) == y] = now;
	tr[now].fa = z;
	pushup(now);
	pushup(y);
	
}

//把 x旋转到 k节点下面
void splay(int x, int k) {
	while (tr[x].fa != k) {
		int y = tr[x].fa, z = tr[y].fa;
		if(z != k) (rs(y) == x) ^ (rs(z) == y) ? rotate(x) : rotate(y);
		rotate(x);
	}
	if(k == 0) root = x;
}

//查找数据
void find(int val) {
	int x = root;
	while(tr[x].s[val > tr[x].val] && val != tr[x].val)
		x = tr[x].s[val > tr[x].val];
	splay(x, 0);
}

//插入数据
void ins(int val) {
	int x = root, p = 0;
	while(x && val != tr[x].val) {
		p = x;
		x = tr[x].s[val > tr[x].val];
	}

	if(!x) { //插入数字不存在
		x = ++idx;
		tr[p].s[val > tr[p].val] = x;
		tr[x].init(p, val);
	} else tr[x].cnt++;//插入数字存在
	splay(x, 0);
}

//找前驱
int get_pre(int val) {
	find(val);
	int x = root;
	if(val > tr[x].val) return x;

	x = ls(x);
	while(tr[x].s[1]) x = rs(x);
	return x;
}

//找后继
int get_next(int val) {
	find(val);
	int x = root;
	if(val < tr[x].val) return x;

	x = rs(x);
	while(tr[x].s[0]) x = ls(x);
	return x;
}
void del(int val){
	int y = get_pre(val), z = get_next(val);
	splay(y, 0);
	splay(z, y);
	int x = tr[z].s[0];
	if(tr[x].cnt > 1) { //左孩子是否有重复
		tr[x].cnt--;
		splay(x, 0);
	} else {
		tr[z].s[0] = 0;
		splay(z, 0);
	}
}
int get_rank(int val) {
	find(val);
	return tr[tr[root].s[0]].siz;
}
int find_rank(int k){
	int x = root;
	while(1) {
		if(tr[tr[x].s[0]].siz + tr[x].cnt < k){
			k -= (tr[tr[x].s[0]].siz + tr[x].cnt);
			x = rs(x);
		} else {
			if(tr[tr[x].s[0]].siz >= k) x = ls(x);
			else break;
		}
	}
	splay(x, 0);
	return tr[x].val;
}
int main() {
	ins(-1e7);
	ins(1e7);
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++){
		int op;
		long long x;
		scanf("%d%lld", &op, &x);
		if(op == 1) ins(x);
		else if(op == 2) del(x);
		else if(op == 3) printf("%d\n", get_rank(x));
		else if(op == 4) printf("%d\n", find_rank(x + 1));
		else if(op == 5) printf("%d\n", tr[get_pre(x)].val);
		else if(op == 6) printf("%d\n", tr[get_next(x)].val);
	}
	return 0;
}
2024/7/16 18:03
加载中...