P3369 【模板】普通平衡树

Description:

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

1.插入x数
2.删除x数(若有多个相同的数,因只删除一个)
3.查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
4.查询排名为x的数
5.求x的前驱(前驱定义为小于x,且最大的数)
6.求x的后继(后继定义为大于x,且最小的数)

Code

hzh

#include<bits/stdc++.h>
#define N 200010
using namespace std;
		   //0:左儿子 1:右儿子 
int dad[N], son[2][N], tot[N], V[N];
int rt, cnt, n, opt, x;
void update(int x){
	//更新节点总数 
	tot[x] = tot[son[0][x]] + tot[son[1][x]] + 1;
}
void rotate(int x){
	int y = dad[x], z = dad[y];
	bool t = son[1][y] == x;//son[t][y] == x
	if(z)son[son[1][z] == y][z] = x;
	son[t][y] = son[!t][x];
	son[!t][x] = y;
	dad[x] = z;
	dad[y] = x;
	dad[son[t][y]] = y;
	update(y);
	update(x);
}
void splay(int x){
	for(; dad[x]; rotate(x))if(dad[dad[x]])
		(son[0][dad[x]] == x) ^ 
		(son[0][dad[dad[x]]] == dad[x]) ?
		rotate(x) : rotate(dad[x]);
	rt = x; 
}
void insert(int &x, int y){//把y点插入以x为根的splay 
	if(!x){
		x = y;
		return;
	}
	if(V[y] <= V[x])
		insert(son[0][x], y), dad[son[0][x]] = x;
	else insert(son[1][x], y), dad[son[1][x]] = x;
	update(x);
}
int findkth(int x, int k){//查询以x为根的splay中第k小的数 
	if(tot[son[0][x]] + 1 == k)
		return x;
	if(tot[son[0][x]] >= k)
		return findkth(son[0][x], k);
	return findkth(son[1][x], k - tot[son[0][x]] - 1);
}
int findkless(int x, int k){
//找到比k小的最大的点 
	if(!x)return 0;
	if(V[x] >= k)
		return findkless(son[0][x], k);
	int t = findkless(son[1][x], k);
	if(t)return t;
	return x;
}
int findkmore(int x, int k){
//找到比k大的最小的点 
	if(!x)return 0;
	if(V[x] <= k)
		return findkmore(son[1][x], k);
	int t = findkmore(son[0][x], k);
	if(t)return t;
	return x;
}
int newpoint(int x){
	cnt++;
	son[0][cnt] = son[1][cnt] = 0;
	dad[cnt] = 0;
	V[cnt] = x;
	tot[cnt] = 1;
	return cnt;
}
void output(){
	printf("%d
", rt);
	for(int i = 1; i <= cnt; i++)
		printf("%d %d %d %d %d
", V[i], dad[i], son[0][i], son[1][i], tot[i]);
	puts("");
}
int main(){
	scanf("%d", &n);
	rt = 0;
	while(n--){
		scanf("%d%d", &opt, &x);
		if(opt == 1){
			int t = newpoint(x);
			insert(rt, t);
			//output();
			splay(t);
		}
		if(opt == 2){
			int t = findkmore(rt, x - 1);
			splay(t);
			dad[son[0][t]] = 0;
			dad[son[1][t]] = 0;
			int s = son[0][t];
			if(!s){
				rt = son[1][t];
				continue; 
			}
			for(; son[1][s]; s = son[1][s]);
			splay(s);
			son[1][s] = son[1][t];
			dad[son[1][t]] = s;
		}
		if(opt == 3){
			int t = findkmore(rt, x - 1);
			splay(t);
			printf("%d
", tot[son[0][t]] + 1);
		}
		if(opt == 4){
			int t = findkth(rt, x);
			splay(t);
			printf("%d
", V[t]);
		}
		if(opt == 5){
			int t = findkless(rt, x);
			splay(t);
			printf("%d
", V[t]);
		}
		if(opt == 6){
			int t = findkmore(rt, x);
			splay(t);
			printf("%d
", V[t]);
		}
	} 
}
岂能尽如人意,但求无愧我心
原文地址:https://www.cnblogs.com/Zforw/p/11250686.html