【模板】Splay

模板题

 

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100000
#define INF 2000000005
struct mzls
{
	mzls *ch[2];
	mzls *fa;
	int key;
	int siz;
}t[N+5];
mzls *root,*NIL,*ncnt;
inline void init()
{
	NIL=ncnt=&t[0];
	NIL->key=-INF;
	root=NIL->ch[0]=NIL->ch[1]=NIL->fa=NIL;
}
inline void PushUp(mzls *s)
{
	s->siz=1;
	s->siz+=s->ch[0]->siz+s->ch[1]->siz;
}
inline void Rotate(mzls *x)
{
	mzls *y=x->fa;
	int d=(x==y->ch[0]);
	x->fa=y->fa;
	if(y->fa!=NIL)
		y->fa->ch[y->fa->ch[1]==y]=x;
	y->ch[!d]=x->ch[d];
	if(x->ch[d]!=NIL)
		x->ch[d]->fa=y;
	x->ch[d]=y;
	y->fa=x;
	if(root==y)
		root=x;
	PushUp(y);
}
inline void Splay(mzls *x,mzls *rt)
{
	mzls *y,*z;
	while(x->fa!=rt)
	{
		y=x->fa,z=y->fa;
		if(z==rt)
			Rotate(x);
		else
		{
			if((y==z->ch[0])^(x==y->ch[0]))
				Rotate(x);
			else
				Rotate(y);
			Rotate(x);
		}
	}
}
inline mzls *New(int val)
{
	mzls *p=++ncnt;
	p->ch[0]=p->ch[1]=p->fa=NIL;
	p->key=val;
	p->siz=1;
	return p;
}
inline void insert(mzls *&rt,mzls *p,int val)
{
	if(rt==NIL)
	{
		rt=New(val);
		rt->fa=p;
		Splay(rt,NIL);
		return;
	}
	rt->siz++;
	insert(rt->ch[val>rt->key],rt,val);
}
inline mzls *Find(mzls *rt,int val)
{
	mzls *p;
	if(rt==NIL)
		return rt;
	if(val==rt->key)
	{
		p=rt->ch[0];
		while(p!=NIL&&p->key==val)
			rt=p,p=p->ch[0];
		Splay(rt,NIL);
		return rt;
	}
	if(val<rt->key)
		p=Find(rt->ch[0],val);
	else
		p=Find(rt->ch[1],val);
	if(p==NIL)
	{
		p=rt;
		Splay(rt,NIL);
	}
	return p;
}
inline mzls *FindPrev(mzls *rt,int val)
{
	if(rt==NIL)
		return NIL;
	mzls *p;
	if(val<=rt->key)
		p=FindPrev(rt->ch[0],val);
	else
	{
		p=FindPrev(rt->ch[1],val);
		if(p==NIL)
		{
			p=rt;
			Splay(rt,NIL);
		}
	}
	return p;
}
inline mzls *FindNext(mzls *rt,int val)
{
	if(rt==NIL)
		return NIL;
	mzls *p;
	if(val>=rt->key)
		p=FindNext(rt->ch[1],val);
	else
	{
		p=FindNext(rt->ch[0],val);
		if(p==NIL)
		{
			p=rt;
			Splay(rt,NIL);
		}
	}
	return p;
}
inline int GetRank(mzls *rt,int val)
{
	if(rt==NIL)
		return 1;
	if(val>rt->key)
		return GetRank(rt->ch[1],val)+rt->ch[0]->siz+1;
	else
		return GetRank(rt->ch[0],val);
}
inline mzls *Select(int k,mzls *f)
{
	mzls *p=root;
	int ml;
	while(1)
	{
		ml=p->ch[0]->siz;
		if(k==ml+1)
			break;
		if(k<=ml)
			p=p->ch[0];
		else
			p=p->ch[1],k-=ml+1;
	}
	Splay(p,f);
	return p;
}
inline void Delete(mzls *rt,int val)
{
	int k=GetRank(rt,val);
	mzls *l=Select(k-1,NIL);
	mzls *r=Select(k+1,l);
	r->ch[0]=NIL;
	Splay(l,NIL);
}
int n,op;
int main()
{
	init();
	scanf("%d",&n);
	insert(root,NIL,INF);
	insert(root,NIL,-INF);
	while(n--)
	{
		int x;
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d",&x);
			insert(root,NIL,x);
		}
		if(op==2)
		{
			scanf("%d",&x);
			Delete(root,x);
		}
		if(op==3)
		{
			scanf("%d",&x);
			printf("%d\n",GetRank(root,x)-1);
		}
		if(op==4)
		{
			scanf("%d",&x);
			printf("%d\n",Select(x+1,NIL)->key);
		}
		if(op==5)
		{
			scanf("%d",&x);
			printf("%d\n",FindPrev(root,x)->key);
		}
		if(op==6)
		{
			scanf("%d",&x);
			printf("%d\n",FindNext(root,x)->key);
		}
	}
}
/*
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值