P3369-[模板]普通平衡树【替罪羊树】

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

正题

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


题目大意

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


解题思路

替罪羊树


c o d e code

#include<cstdio>
#include<algorithm>
#include<cctype>
#define alpha 0.8
#define N 100010
using namespace std;
inline int read(){
    int x(0),sign(0);
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') sign=1;
        ch=getchar();
    }
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return sign?-x:x;
}
struct goat_Tree{
	int l[N],r[N],size[N],val[N],valid[N],total[N];
	int cur[N],memory[N];
	bool exist[N];
	int root,poi,pool,cnt;
	void ReMemory(){
	    for(int i=N-10;i>=1;i--)
	    memory[++pool]=i;
	}
	bool Isbad(int now){
		if((double)valid[now]*alpha<=(double)max(valid[l[now]],valid[r[now]]))
		  return true;
		else return false;
	}
	void Beat(int now){
		if(!now) return;
		Beat(l[now]);
		if(exist[now]) cur[++poi]=now;
		else memory[++pool]=now;
		Beat(r[now]);
	}
	void New(int x){
		l[x]=r[x]=0;
		total[x]=valid[x]=1;
	}
	void Build(int ls,int rs,int &now){
		int mid=(ls+rs)>>1;
		now=cur[mid];
		if(ls==rs){
			New(now);
			return;
		}
		if(ls<mid) Build(ls,mid-1,l[now]);
		else l[now]=0;
		Build(mid+1,rs,r[now]);
		total[now]=total[l[now]]+total[r[now]]+1;
		valid[now]=valid[l[now]]+valid[r[now]]+1;
	}
	void ReBuild(int &now){
		poi=0;Beat(now);
		if(poi) Build(1,poi,now);
		else now=0;
	}
	int GetRankByVal(int k){
		int now=root;
		int ans=1;
		while(now){
			if(val[now]>=k) now=l[now];
			else{
				ans+=valid[l[now]]+exist[now];
				now=r[now];
			}
		}
		return ans;
	}
	int GetValByRank(int k){
		int now=root;
		while(now){
			if(exist[now]&&valid[l[now]]+1==k)
			  return val[now];
			if(valid[l[now]]>=k) now=l[now];
			else{
				k-=valid[l[now]]+exist[now];
				now=r[now];
			}
		}
	}
	void Insert(int &now,int num){
		if(!now){
			now=memory[pool--];val[now]=num;
			New(now);exist[now]=1;
			return;
		}
		total[now]++;valid[now]++;
		if(val[now]>=num) Insert(l[now],num);
		else Insert(r[now],num);
		if(Isbad(now))
		  ReBuild(now);
	}
	void Remove_z(int &now,int tar){
		if(exist[now]&&valid[l[now]]+1==tar){
			exist[now]=0;valid[now]--;
			return;
		}
		valid[now]--;
		if(valid[l[now]]+exist[now]>=tar)
		  Remove_z(l[now],tar);
		else Remove_z(r[now],tar-valid[l[now]]-exist[now]);
	}
	void Remove(int tar){
		Remove_z(root,GetRankByVal(tar));
		if((double)total[root]*alpha>valid[root])
		  ReBuild(root);
	}
}a;
int main()
{
	int opt,x,m;
	a.ReMemory();
	scanf("%d",&m);
	while(m--)
	{
		opt=read();x=read();
		if(opt==1) a.Insert(a.root,x);
		if(opt==2) a.Remove(x);
		if(opt==3) printf("%d\n",a.GetRankByVal(x));
		if(opt==4) printf("%d\n",a.GetValByRank(x));
		if(opt==5) printf("%d\n",a.GetValByRank(a.GetRankByVal(x)-1));
		if(opt==6) printf("%d\n",a.GetValByRank(a.GetRankByVal(x+1)));
	}
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/85829424
今日推荐