【模板】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,且最小的數)
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章