【模板】伸展树Splay(数组实现)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82934272

参考题目:LOJ107


解析:

联赛完后统一更模板题题解。
指针版本的代码在这里.


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
int getint(){
	re int num;
	re char c;
	re bool f=0;
	while(!isdigit(c=gc()))f^=c=='-';num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return f?-num:num; 
}

inline
void outint(int a){
	static char ch[13];
	if(a==0)pc('0');
	if(a<0)pc('-'),a=-a;
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

cs int N=300005;
struct SPLAY{
	int son[N][2];
	#define lc(k) son[k][0]
	#define rc(k) son[k][1]
	int val[N],fa[N];
	int cnt[N],siz[N];
	int tot,root;
	SPLAY():tot(0),root(0){}
	bool which(int k){
		return k==rc(fa[k]);
	}
	void update(int k){
		siz[k]=(lc(k)?siz[lc(k)]:0)+(rc(k)?siz[rc(k)]:0)+cnt[k];
	}
	void init(int k){
		lc(k)=rc(k)=fa[k]=0;
		siz[k]=cnt[k]=1;
	}
	void clear(int k){
		lc(k)=rc(k)=0;
		val[k]=siz[k]=cnt[k]=0;
	}
	
	void Rotate(int now){
		int Fa=fa[now];
		bool pos=!which(now);
		son[Fa][!pos]=son[now][pos];
		if(son[now][pos])fa[son[now][pos]]=Fa;
		if(fa[now]=fa[Fa])son[fa[now]][which(Fa)]=now;
		fa[Fa]=now;
		son[now][pos]=Fa;
		update(Fa);
		update(now);
		if(!fa[now])root=now; 
	}
	
	void Splay(int now,int to=0){
		for(int Fa=fa[now];(Fa=fa[now])!=to;Rotate(now))
		if(fa[Fa]!=to)Rotate((which(now)==which(Fa))?Fa:now);
	}
	
	void Insert(cs int &key){
		if(!root){
			init(root=++tot);
			val[root]=key;
			return ;
		}
		int now=root,Fa;
		for(;;Fa=now,now=son[now][key>val[now]]){
			if(!now){
				init(now=++tot);
				fa[now]=Fa;
				val[now]=key;
				son[Fa][key>val[Fa]]=now;
				return Splay(now);
			}
			if(val[now]==key){
				++cnt[now];
				Splay(now);
				return ;
			}
		}
	}
	
	int find(cs int &key){
		int now=root;
		while(now&&val[now]!=key)now=son[now][key>val[now]];
		if(now)Splay(now);
		return now;
	}
	
	int pre_pos(cs int &key){
		int now=find(key);
		re bool flag=false;
		if(!now){
			Insert(key);
			now=root;
			flag=true;
		}
		if(!lc(now)){
			if(flag)Delete(key);
			return 0;
		}
		for(now=lc(now);rc(now);now=rc(now));
		if(flag)Delete(key);
		return now;
	}
	
	void Delete(cs int &key){
		int now=find(key);
		if(!now)return ;
		if(cnt[now]>1){
			--cnt[now];
			--siz[now];
			return ;
		}
		if(!lc(now)&&!rc(now)){
			clear(now);
			root=0;
			return ;
		}
		if(!lc(now)){
			root=rc(now);
			fa[rc(now)]=0;
			clear(now);
			return;
		}
		if(!rc(now)){
			root=lc(now);
			fa[lc(now)]=0;
			clear(now);
			return ;
		}
		int res_pre=pre_pos(val[now]);
		int res=root;
		Splay(res_pre);
		rc(root)=rc(res);
		fa[rc(res)]=root;
		update(root);
	}
	
	int querykth(int key){
		re int ans=0;
		re int res;
		re int now=root;
		while(true){
			if(lc(now)&&key<=siz[lc(now)]){
				now=lc(now);
				continue;
			}
			res=(lc(now)?siz[lc(now)]:0)+cnt[now];
			if(key<=res)return val[now];
			key-=res;
			now=rc(now);
		}
	}
	
	int queryrank(cs int &key){
		int now=find(key);
		re bool flag=false;
		if(!now){
			Insert(key);
			flag=true;
		}
		int ans=siz[root];
		if(rc(root))ans-=siz[rc(root)];
		ans-=cnt[root];
		if(flag)Delete(key);
		return ans;
	}
	
	int querypre(cs int &key){
		int now=find(key);
		re bool flag=false;
		if(!now){
			Insert(key);
			now=root;
			flag=true;
		}
		if(!lc(now)){
			if(flag)Delete(key);
			return -1;
		}
		for(now=lc(now);rc(now);now=rc(now));
		if(flag)Delete(key);
		return val[now];
	}
	
	int querysuf(cs int &key){
		int now=find(key);
		re bool flag=false;
		if(!now){
			Insert(key);
			now=root;
			flag=true;
		}
		if(!rc(now)){
			if(flag)Delete(key);
			return -1;
		}
		for(now=rc(now);lc(now);now=lc(now));
		if(flag)Delete(key);
		return val[now];
	}
	
}splay;

int n;
signed main(){
	n=getint();
	while(n--){
		int op=getint(),x=getint();
		switch(op){
			case 0:{splay.Insert(x);break;}
			case 1:{splay.Delete(x);break;}
			case 2:{outint(splay.querykth(x)),pc('\n');break;}
			case 3:{outint(splay.queryrank(x)),pc('\n');break;}
			case 4:{outint(splay.querypre(x)),pc('\n');break;}
			case 5:{outint(splay.querysuf(x)),pc('\n');break;}
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82934272