P3369-[模板]普通平衡树【有旋Treap】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/85798741

正题

评测记录:https://www.luogu.org/recordnew/lists?uid=SSL_WYC_zombieeeeee&pid=P3369&status=&sort=0


题目大意

要求支持查询一个数字的排名,查询该排名的数字,插入数字,删除数字,求前驱后继。


解题思路

有旋Treap不解释。


c o d e code

#include<cstdio>
#include<algorithm>
#define INF 2147483647/3
#define N 100010
using namespace std;
int n,root;
struct Treap_node{
	int l[N],r[N];
	int val[N],dat[N];
	int cnt[N],size[N];
	int tot;
	int New(int new_val){
		val[++tot]=new_val;
		dat[tot]=rand();
		cnt[tot]=size[tot]=1;
		return tot;
	}
	void Updata(int p){
		size[p]=size[l[p]]+size[r[p]]+cnt[p];
	}
	void Build(){
		New(-INF);New(INF);
		root=1;r[1]=2;
		Updata(root);
	}
	int GetRankByVal(int p,int num){
		if(p==0) return 0;
		if(num==val[p]) return size[l[p]]+1;
		if(num<val[p]) return GetRankByVal(l[p],num);
		return GetRankByVal(r[p],num)+size[l[p]]+cnt[p];
	}
	int GetValByRank(int p,int rank){
		if (p==0) return INF;
		if(size[l[p]]>=rank) return GetValByRank(l[p],rank);
		if(size[l[p]]+cnt[p]>=rank) return val[p];
		return GetValByRank(r[p],rank-size[l[p]]-cnt[p]);
	}
	void zig(int &p){
		int q=l[p];
		l[p]=r[q];r[q]=p;p=q;
		Updata(r[p]);Updata(p);
	}
	void zag(int &p){
		int q=r[p];
		r[p]=l[q];l[q]=p;p=q;
		Updata(l[p]);Updata(p);
	}
	void Insert(int &p,int num){
		if(p==0){
			p=New(num);
			return;
		}
		if(num==val[p]){
			cnt[p]++;Updata(p);
			return;
		}
		if(num<val[p]){
			Insert(l[p],num);
			if(dat[p]<dat[l[p]]) zig(p);
		}
		else{
			Insert(r[p],num);
			if(dat[p]<dat[r[p]]) zag(p);
		}
		Updata(p);
	}
	int GetPre(int num){
		int ans=1;
		int p=root;
		while(p){
			if(num==val[p]){
				if(l[p]>0){
					p=l[p];
					while(r[p]>0) p=r[p];
					ans=p;
				}
				break;
			}
			if(val[p]<num&&val[p]>val[ans]) ans=p;
			p=num<val[p]?l[p]:r[p];
		}
		return val[ans];
	}
	int GetNext(int num){
		int ans=2;
		int p=root;
		while(p){
			if(num==val[p]){
				if(r[p]>0){
					p=r[p];
					while(l[p]>0) p=l[p];
					ans=p;
				}
				break;
			}
			if(val[p]>num&&val[p]<val[ans]) ans=p;
			p=num<val[p]?l[p]:r[p];
		}
		return val[ans];
	}
	void Remove(int &p,int num){
		if(p==0) return;
		if(num==val[p]){
			if(cnt[p]>1){
				cnt[p]--;Updata(p);
				return;
			}
			if(l[p]||r[p]){
				if(r[p]==0||dat[l[p]]>dat[r[p]])
			  	  zig(p),Remove(r[p],num);
				else
			      zag(p),Remove(l[p],num);
				Updata(p);
			}
			else p=0;
			return;
		}
		num<val[p]?Remove(l[p],num):Remove(r[p],num);
		Updata(p);
	}
}a;
int main()
{
	a.Build();
	scanf("%d",&n);
	while(n--){
		int opt,x;
		scanf("%d%d",&opt,&x);
		switch(opt){
			case 1:
				a.Insert(root,x);
				break;
			case 2:
				a.Remove(root,x);
				break;
			case 3:
				printf("%d\n",a.GetRankByVal(root,x)-1);
				break;
			case 4:
				printf("%d\n",a.GetValByRank(root,x+1));
				break;
			case 5:
				printf("%d\n",a.GetPre(x));
				break;
			case 6:
				printf("%d\n",a.GetNext(x));
				break;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/85798741