【模板】Splay (仅代码纯享版)

#include<cstdio>
#include<algorithm>
#define lson(x) tr[x].ch[0]
#define rson(x) tr[x].ch[1]
#define fa(x) tr[x].fa

using namespace std;

const int MAXN = 1e5 + 10;
const int INF = 2147483647;
int n;

inline int read(){
	int x = 0, f = 1;
	char c = getchar();

	while(c < '0' || c > '9'){
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9'){
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}

	return x * f;
}

struct Splay{
	int tot, root;
	struct Tree{
		int fa; //父节点
		int val; //权值
		int num; //这个权值的节点出现的个数
		int size; //子节点的数量
		int ch[2]; //ch[0] 左孩子,ch[1] 右孩子

		Tree(){
			fa = val = num = size = 0;
			ch[0] = ch[1] = 0;
		}
	}tr[MAXN];

	Splay(){
		tot = root = 0;
	}

	void Pushup(int rt){ //更新
		tr[rt].size = tr[lson(rt)].size + tr[rson(rt)].size + tr[rt].num;
	}

	int Get_son(int rt){ //如果是右儿子,返回一,左儿子返回0
		return rt == rson(fa(rt)) ? 1 : 0;
	}

	void Connect(int rt, int fa, int d){
		tr[fa].ch[d] = rt;
		fa(rt) = fa;
	}

	void Rotate(int rt){ //旋转节点 rt 到他父亲的位置  
		int fa = fa(rt); // rt 的父亲 
		int gr_fa = fa(fa); // rt 的祖父
		int d1 = Get_son(rt); // rt 是 fa 的哪一个孩子
		int d2 = Get_son(fa); // fa 是 gr_fa 的哪一个孩子

		Connect(tr[rt].ch[d1 ^ 1], fa, d1);
		Connect(fa, rt, d1 ^ 1);
		Connect(rt, gr_fa, d2);
		
		Pushup(fa);
		Pushup(rt);
		//这样,rt 就成功越位,晋升成了他祖父的儿子,他跌成了他的儿子(超级加倍)
	}

	//revolve 也是旋转的意思,因为 Splay 命名结构体了,Rotate 也用过了
	void Revolve(int rt, int goal){ //将 rt 旋转到 goal 
		goal = fa(goal);
		
		while(fa(rt) != goal){
            if(fa(fa(rt)) == goal)
				Rotate(rt);
			else if(Get_son(rt) == Get_son(fa(rt))){ //函数名一定要有区分度,Get_son 和 Get 的区别,还有,封装在结构体里边他不报错啊  
				Rotate(fa(rt));
				Rotate(rt);
			} 
			else{
				Rotate(rt);
				Rotate(rt);
			}
		}
		
		if(goal == 0){
			root = rt;
			Connect(rt, 0, 1);
		}
	}

	void Build(int val, int fa, int d){//新建一个权值为val,是 fa 结点的 d 孩子的结点
		int rt = ++tot;
		
		tr[rt].fa = fa;
		tr[rt].val = val;
		tr[rt].num = tr[rt].size = 1;
		tr[fa].ch[d] = rt;
	}

	void Insert(int val){ //插入一个值
		if(root == 0){
			Build(val, 0, 1);
			root = tot;
			return;
		}
		
		int rt = root;
		
		while(1){
			tr[rt].size++;
			if(val == tr[rt].val){
				tr[rt].num++;
				Revolve(rt, root);
				return;
			}
			
			int d = tr[rt].val < val ? 1 : 0;
			int son = tr[rt].ch[d];
			
			if(!son){
				Build(val, rt, d);
				Revolve(tot, root);
				return;
			}
			
			rt = son;
		}
	}

	int Get(int val){
		int rt = root;
		
		while(1){
			if(!rt) return 0;
			if(tr[rt].val == val){
				Revolve(rt, root);
				return rt;
			}
			
			int d = tr[rt].val < val ? 1 : 0;
			int son = tr[rt].ch[d];
			
			rt = son;
		}
	}

	void Delete(int val){
		int rt = Get(val);

		if(!rt) return;
		if(tr[rt].num > 1){
			tr[rt].num--;
			tr[rt].size--;
			return;
		}
		
		if(!lson(rt) && !rson(rt))
			root = 0;
		else if(!lson(rt)){
			root = rson(root);
			tr[root].fa = 0;
		}
		else if(!rson(rt)){
			root = lson(root);
			tr[root].fa = 0;
		}
		else{
			int pos = lson(rt);
			
			while(rson(pos)) pos = rson(pos);
			
			Revolve(pos, root);
			Connect(rson(rt), pos, 1);
			Pushup(pos);
		}
	}

	int Rank(int val){
		int rt = root, ans = 0;
		
		while(rt){
			if(tr[rt].val == val){
				Revolve(rt, root);
				return tr[lson(rt)].size + 1;
			}
			if(tr[rt].val < val){
				ans = ans + tr[lson(rt)].size + tr[rt].num;
				rt = rson(rt);
			}
			else
				rt = lson(rt);
		}
		
		return ans + 1;
	}

	int Find(int pos){
		int rt = root;

		while(1){
			int used = tr[rt].size - tr[rson(rt)].size;

			if(pos > tr[lson(rt)].size && pos <= used) break;
			if(pos >= used){
				pos -= used;
				rt = rson(rt);
			}
			else
				rt = lson(rt);
		}

		Revolve(rt, root);

		return tr[rt].val;
	}

	int Pre(int val){
		int rt = root;
		int ans = -INF;

		while(rt){
			if(tr[rt].val < val && tr[rt].val > ans)
				ans = tr[rt].val;
			if(tr[rt].val < val)
				rt = rson(rt);
			else
				rt = lson(rt);
		}

		return ans;
	}

	int Suf(int val){
		int rt = root;
		int ans = INF;

		while(rt){
			if(tr[rt].val > val && tr[rt].val < ans)
				ans = tr[rt].val;
			if(tr[rt].val > val)
				rt = lson(rt);
			else
				rt = rson(rt);
		}

		return ans;
	}
}S;

int main(){
	n = read();
	for(register int i = 1; i <= n; i++){
		int opt, x;
		
		opt = read(), x = read();
		if(opt == 1) S.Insert(x);
		else if(opt == 2) S.Delete(x);
		else if(opt == 3) printf("%d\n", S.Rank(x));
		else if(opt == 4) printf("%d\n", S.Find(x));
		else if(opt == 5) printf("%d\n", S.Pre(x));
		else if(opt == 6) printf("%d\n", S.Suf(x));
	}
	
	return 0;
}

posted @ 2022-08-03 21:57  TSTYFST  阅读(69)  评论(0编辑  收藏  举报