平衡树

普通二叉树与平衡树初步

无旋Treap,Treap,Splay

见题库-网课-Treap和Splay。

普通平衡树

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入数值x。
  2. 删除数值x(若有多个相同的数,应只删除一个)。
  3. 查询数值x的排名(若有多个相同的数,应输出最小的排名)。
  4. 查询排名为x的数值。
  5. 求数值x的前驱(前驱定义为小于x的最大的数)。
  6. 求数值x的后继(后继定义为大于x的最小的数)。

注意: 数据保证查询的结果一定存在。

输入格式

第一行为n,表示操作的个数。

接下来n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)。

输出格式

对于操作3,4,5,6每行输出一个数,表示对应答案。

数据范围

n≤100000n≤100000,所有数均在−107−107到107107内。

输入样例:

8
1 10
1 20
1 30
3 20
4 2
2 10
5 25
6 -1

输出样例:

2
20
20
20
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,INF=0x7fffffff;
int n,tot,root;
int lc[N],rc[N],val[N],dat[N],cnt[N],siz[N];

int add(int x)
{
	val[++tot]=x;
	dat[tot]=rand();
	cnt[tot]=siz[tot]=1;
	return tot;
}

void update(int p)
{
	siz[p]=siz[lc[p]]+siz[rc[p]]+cnt[p];
}

void Build()
{
	root=add(-INF);
	rc[root]=add(INF);
	root=1;rc[1]=2;
	update(root);
}

void lup(int &p)
{
	int q=lc[p];
	lc[p]=rc[q];rc[q]=p;p=q;
	update(rc[p]);update(p);
}

void rup(int &p)
{
	int q=rc[p];
	rc[p]=lc[q];lc[q]=p;p=q;
	update(lc[p]);update(p);
}

void Insert(int &p,int x)
{
	if(!p)
	{
		p=add(x);
		return;
	}
	if(val[p]==x)
	{
		cnt[p]++;
		update(p);
		return;
	}
	if(x<val[p])
	{
		Insert(lc[p],x);
		if(dat[lc[p]]>dat[p]) lup(p);
	}
	else
	{
		Insert(rc[p],x);
		if(dat[rc[p]]<dat[p]) rup(p);
	}
	
	update(p);
}

void Delete(int &p,int x)
{
	if(!p) return;
	
	if(x==val[p])
	{
		if(cnt[p]>1)
		{
			cnt[p]--;
			update(p);
			return;
		}
		else
		{
			if(lc[p]||rc[p])
			{
				if(!rc[p]||dat[lc[p]]>dat[rc[p]]) lup(p),Delete(rc[p],x);
				else rup(p),Delete(lc[p],x);
				update(p);
				
			}
			else p=0;
			return;
		}
	}
	Delete(x<val[p]?lc[p]:rc[p],x);
	update(p);
}

int Grbv(int p,int x)
{
	if(!p) return 0;
	if(x<val[p]) return Grbv(lc[p],x);
	if(x>val[p]) return siz[lc[p]]+cnt[p]+Grbv(rc[p],x);
	return siz[lc[p]]+1;
}

int Gvbr(int p,int x)
{
	if(!p) return INF;
	if(x<=siz[lc[p]]) return Gvbr(lc[p],x);
	if(x<=siz[lc[p]]+cnt[p]) return val[p];
	return Gvbr(rc[p],x-siz[lc[p]]-cnt[p]);
}

int Pre(int x)
{
	int p=root,pos=1;
	while(p)
	{
		if(val[p]==x)
		{
			if(lc[p])
			{
				p=lc[p];
				while(rc[p]) p=rc[p];
				pos=p;
			}
			break;
		}
		if(val[p]<x&&val[p]>val[pos]) pos=p;
		p=x<val[p]?lc[p]:rc[p];
	}
	
	return val[pos];
}

int Next(int x)
{
	int p=root,pos=2;
	while(p)
	{
		if(val[p]==x)
		{
			if(rc[p])
			{
				p=rc[p];
				while(lc[p]) p=lc[p];
				pos=p;
			}
			break;
		}
		if(val[p]>x&&val[p]<val[pos]) pos=p;
		p=x<val[p]?lc[p]:rc[p];
	}
	
	return val[pos];
}

int main()
{
	Build();
	scanf("%d",&n);
	
	while(n--)
	{
		int opx,x;
		scanf("%d %d",&opx,&x);
		switch(opx)
		{
			case 1:{Insert(root,x);break;}
			case 2:{Delete(root,x);break;}
			case 3:{printf("%d\n",Grbv(root,x)-1);break;}
			case 4:{printf("%d\n",Gvbr(root,x+1));break;}
			case 5:{printf("%d\n",Pre(x));break;}
			case 6:{printf("%d\n",Next(x));break;}
		}
	}
	return 0;
} 
posted @ 2020-10-23 19:15  林生。  阅读(70)  评论(0)    收藏  举报