平衡树

记录下我的板子,题源 https://www.luogu.com.cn/problem/P3369

Splay

#include <bits/stdc++.h>
using namespace std;
const int inf=1e9;
int n,root,tot;
struct splay{
	int ch[3],val,cnt;
	int size,fa;
}a[1000010];
void Update(int p){
	a[p].size=a[a[p].ch[0]].size+a[a[p].ch[1]].size+a[p].cnt;
}
void Rotate(int x){
	int y=a[x].fa;
	int z=a[y].fa;
	int kid=a[y].ch[1]==x;
	a[z].ch[a[z].ch[1]==y]=x;
	a[x].fa=z;
	a[y].ch[kid]=a[x].ch[kid^1];
	a[a[x].ch[kid^1]].fa=y;
	a[x].ch[kid^1]=y;
	a[y].fa=x;
	Update(y);
	Update(x);
}
void Splay(int x,int goal){
	while(a[x].fa!=goal){
		int y=a[x].fa;
		int z=a[y].fa;
		if(z!=goal){
			(a[z].ch[1]==y)^(a[y].ch[1]==x)?Rotate(x):Rotate(y);
		}
		Rotate(x);
	}
	if(goal==0){
		root=x;
	}
}
void Insert(int val){
	int now=root,fa=0;
	while(now&&a[now].val!=val){
		fa=now;
		now=a[now].ch[a[now].val<val];
	}
	if(now){
		a[now].cnt++;
	}
	else{
		now=++tot;
		if(fa){
			a[fa].ch[a[fa].val<val]=now;
			a[now].fa=fa;
		}
		a[now].val=val;
		a[now].size=a[now].cnt=1;
	}
	Splay(now,0);
}
void Search(int val){
	int now=root;
	if(!now){
		return ;
	}
	while(a[now].val!=val&&a[now].ch[a[now].val<val]){
		now=a[now].ch[a[now].val<val];
	}
	Splay(now,0);
}
int GetValByRank(int p,int rank){
	if(!p){
		return 0;
	}
	if(a[a[p].ch[0]].size>=rank){
		return GetValByRank(a[p].ch[0],rank);
	}
	if(a[a[p].ch[0]].size+a[p].cnt>=rank){
		return a[p].val;
	}
	return GetValByRank(a[p].ch[1],rank-a[a[p].ch[0]].size-a[p].cnt);
	
}
int GetPre(int val){
	Search(val);
	int pos=a[root].ch[0];
	while(a[pos].ch[1]){
		pos=a[pos].ch[1];
	}
	return pos;
}
int GetNext(int val){
	Search(val);
	int pos=a[root].ch[1];
	while(a[pos].ch[0]){
		pos=a[pos].ch[0];
	}
	return pos;
}
void Remove(int x){
	int pre_x=GetPre(x);
	int nxt_x=GetNext(x);
	Splay(pre_x,0);
	Splay(nxt_x,pre_x);
	int pos=a[root].ch[1];
	if(a[a[pos].ch[0]].cnt>1){
		a[a[pos].ch[0]].cnt--;
		Update(nxt_x);
		Update(pre_x);
		Splay(a[pos].ch[0],0);
		return ;
	}
	a[pos].ch[0]=0;
	Update(nxt_x);
	Update(pre_x);
	return ;
}
signed main(){
	ios::sync_with_stdio(0);
	cin>>n;
	Insert(-inf);
	Insert(inf);
	for(int i=1;i<=n;i++){
		int opt,x;
		cin>>opt>>x;
		if(opt==1){
			Insert(x);
		}
		if(opt==2){
			Remove(x);
		}
		if(opt==3){
			Insert(x);
			Search(x);
			cout<<a[a[root].ch[0]].size<<endl;
			Remove(x);
		}
		if(opt==4){
			cout<<GetValByRank(root,x+1)<<endl;
		}
		if(opt==5){
			Insert(x);
			cout<<a[GetPre(x)].val<<endl;
			Remove(x);
		}
		if(opt==6){
			Insert(x);
			cout<<a[GetNext(x)].val<<endl;
			Remove(x);
		}
	}
}

Treap

#include <bits/stdc++.h>
using namespace std;
const int inf=0x7fffffff;
int n,tot,root;
struct Treap{
	int l,r;
	int dat,val;
	int size,cnt;
}a[100010];
void Update(int p){
	a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
}
int New(int val){
	a[++tot].val=val;
	a[tot].dat=rand();
	a[tot].size=a[tot].cnt=1;
	return tot;
}
void Build(){
	New(-inf);
	New(inf);
	root=1;
	a[1].r=2;
	Update(root);
}
void zig(int &p){
	int q=a[p].l;
	a[p].l=a[q].r;
	a[q].r=p;
	p=q;
	Update(a[p].r);
	Update(p);
}
void zag(int &p){
	int q=a[p].r;
	a[p].r=a[q].l;
	a[q].l=p;
	p=q;
	Update(a[p].l);
	Update(p);
}
void Insert(int &p,int val){
	if(p==0){
		p=New(val);
		return ;
	}
	if(a[p].val==val){
		a[p].cnt++;
		Update(p);
		return ;
	}
	if(val<a[p].val){
		Insert(a[p].l,val);
		if(a[a[p].l].dat>a[p].dat){
			zig(p);
		}
	}
	else{
		Insert(a[p].r,val);
		if(a[a[p].r].dat>a[p].dat){
			zag(p);
		}
	}
	Update(p);
}
int GetRankByVal(int p,int val){
	if(p==0){
		return 0;
	}
	if(val==a[p].val){
		return a[a[p].l].size+1;
	}
	if(val<a[p].val){
		return GetRankByVal(a[p].l,val);
	}
	return GetRankByVal(a[p].r,val)
		+a[a[p].l].size+a[p].cnt;
}
int GetValByRank(int p,int rank){
	if(p==0){
		return inf;
	}
	if(a[a[p].l].size>=rank){
		return GetValByRank(a[p].l,rank);
	}
	if(a[a[p].l].size+a[p].cnt>=rank){
		return a[p].val;
	}
	return GetValByRank(a[p].r,rank-a[a[p].l].size-a[p].cnt);
}
int GetPre(int val){
	int ans=1;
	int p=root;
	while(p){
		if(a[p].val==val){
			if(a[p].l>0){
				p=a[p].l;
				while(a[p].r>0){
					p=a[p].r;
				}
				ans=p;
			}	
			break;
		}
		if(a[p].val>a[ans].val&&a[p].val<val){
			ans=p;
		}
		p=val<a[p].val?a[p].l:a[p].r;
	}
	return a[ans].val;
}
int GetNext(int val){
	int ans=2;
	int p=root;
	while(p){
		if(a[p].val==val){
			if(a[p].r>0){
				p=a[p].r;
				while(a[p].l>0){
					p=a[p].l;
				}
				ans=p;
			}
			break;
		}
		if(a[p].val<a[ans].val&&a[p].val>val){
			ans=p;
		}
		p=val<a[p].val?a[p].l:a[p].r;
	}
	return a[ans].val;
}
void Remove(int &p,int val){
	if(p==0){
		return ;
	}
	if(val==a[p].val){
		if(a[p].cnt>1){
			a[p].cnt--;
			Update(p);
			return ;
		}
		if(a[p].l||a[p].r){
			if(a[p].r==0||a[a[p].l].dat>a[a[p].r].dat){
				zig(p);
				Remove(a[p].r,val);
			}
			else{
				zag(p);
				Remove(a[p].l,val);
			}
			Update(p);
		}
		else{
			p=0;
			return ;
		}
	}
	
	val<a[p].val?Remove(a[p].l,val):Remove(a[p].r,val);
	Update(p);
}
int main(){
	ios::sync_with_stdio(0);
	srand(0);
	Build();
	cin>>n;
	for(int i=1;i<=n;i++){
		int op,x;
		cin>>op>>x;
		if(op==1){
			Insert(root,x);
		}
		if(op==2){
			Remove(root,x);
		}
		if(op==3){
			Insert(root,x);
			cout<<GetRankByVal(root,x)-1<<endl;
			Remove(root,x);
		}
		if(op==4){
			cout<<GetValByRank(root,x+1)<<endl;
		}
		if(op==5){
			cout<<GetPre(x)<<endl;
		}
		if(op==6){
			cout<<GetNext(x)<<endl;
		}
	}
}
posted @ 2025-12-25 21:52  heccqwq  阅读(6)  评论(0)    收藏  举报