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

传送门

这年头找个好点的SplaySplay板子好难的

还是看的yybyyb

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

注意由于deletedelete的方法比较特殊,需要对前驱后继操作

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

#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;
			}
		}
	}
}
posted @ 2019-01-23 11:41  Stargazer_cykoi  阅读(129)  评论(0编辑  收藏  举报