【TYVJ1728】【洛谷P3369】—普通平衡树(Splay写法)

传送门

这年头找个好点的 S p l a y Splay 板子好难的

还是看的 y y b yyb

操作都是常规的,对着代码看一下就懂了

注意由于 d e l e t e delete 的方法比较特殊,需要对前驱后继操作

所以为了保证每次都一定有前驱后继要先加一个极大值和一个极小值

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
}
const int N=100006;
int n,m,rt,tot;
int fa[N],siz[N],son[N][2],val[N],cnt[N];
#define lc(u) (son[u][0])
#define rc(u) (son[u][1])
inline void pushup(int u){
	siz[u]=siz[lc(u)]+siz[rc(u)]+cnt[u];
}
inline void rotate(int v){
	int u=fa[v],z=fa[u];
	int t=(rc(u)==v);
	son[z][rc(z)==u]=v;
	fa[v]=z;
	son[u][t]=son[v][t^1];
	fa[son[v][t^1]]=u;
	fa[u]=v,son[v][t^1]=u;
	pushup(u),pushup(v);
}
inline void splay(int v,int goal){
	while(fa[v]!=goal){
		int u=fa[v],z=fa[u];
		if(z!=goal)
			(lc(z)==u)^(lc(u)==v)?rotate(v):rotate(u);
		rotate(v);
	}
	if(goal==0)rt=v;
}
inline void insert(int x){
	int u=rt,f=0;
	while(u&&val[u]!=x){
		f=u,u=son[u][x>val[u]];
	}
	if(u)cnt[u]++;
	else{
		u=++tot;
		if(f)son[f][x>val[f]]=u;
		lc(u)=rc(u)=0;
		fa[u]=f,val[u]=x,siz[u]=cnt[u]=1;
	}
	splay(u,0);
}
inline void find(int x){
	int u=rt;
	if(!u)return;
	while(son[u][x>val[u]]&&val[u]!=x)
		u=son[u][x>val[u]];
	splay(u,0);
}
inline int pre(int x){
	find(x);
	int u=rt;
	if(val[u]<x)return u;
	u=lc(u);
	while(rc(u))u=rc(u);
	return u;
}
inline int nxt(int x){
	find(x);
	int u=rt;
	if(val[u]>x)return u;
	u=rc(u);
	while(lc(u))u=lc(u);
	return u;
}
inline void delet(int x){
	int last=pre(x),next=nxt(x);
	splay(last,0),splay(next,last);
	int del=lc(next);
	if(cnt[del]>1)cnt[del]--,splay(del,0);
	else lc(next)=0;
}
inline int kth(int x){
	int u=rt;
	if(siz[u]<x)return 0;
	while(1){
		int y=lc(u);
		if(x>siz[y]+cnt[u]){
			x-=siz[y]+cnt[u];
			u=rc(u);
		}
		else {
			if(x<=siz[y]){
				u=y;
			}
			else return val[u];
		}
	}
}
int main(){
	n=read();
	insert(20030224);
	insert(-20030224);
	for(int i=1;i<=n;i++){
		int op=read(),x=read();
		switch(op){
			case 1:{
				insert(x);
				break;
			}
			case 2:{
				delet(x);
				break;
			}
			case 3:{
				find(x);
				cout<<siz[lc(rt)]<<'\n';
				break;
			}
			case 4:{
				cout<<kth(x+1)<<'\n';
				break;
			}
			case 5:{
				cout<<val[pre(x)]<<'\n';
				break;
			}
			case 6:{
				cout<<val[nxt(x)]<<'\n';
				break;
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/86607510
今日推荐