【学习笔记】平衡树

P3369 普通平衡树

  • 无旋treap最基本的三个函数spirit,merge,kth,其他函数都基于这三个函数操作的
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
mt19937 rnd(time(0));
struct node{
	int siz,val,rans;
	int son[2];
	#define siz(q) tree[q].siz
	#define val(q) tree[q].val
	#define rans(q) tree[q].rans
	#define ls(q) tree[q].son[0]
	#define rs(q) tree[q].son[1]
}tree[N];
int root,idx;
int add(int x){
	++idx;
	siz(idx)=1;
	val(idx)=x;
	rans(idx)=rnd();
	ls(idx)=rs(idx)=0;
	return idx;
}
void push_up(int q){
	siz(q)=siz(ls(q))+siz(rs(q))+1;
}
void spirit(int q,int x,int &l,int &r){
	if(q==0) return l=r=0,void();
	if(val(q)<=x) l=q,spirit(rs(q),x,rs(q),r);
	else r=q,spirit(ls(q),x,l,ls(q));
	push_up(q);
}
int merge(int a,int b){
	if(!a||!b) return a+b;
	if(rans(a)<rans(b)){
		rs(a)=merge(rs(a),b);
		push_up(a);
		return a;
	}
	else{
		ls(b)=merge(a,ls(b));
		push_up(b);
		return b;		
	}
}
int kth(int q,int x){
	if(siz(ls(q))+1==x) return q;
	if(x<=siz(ls(q))) return kth(ls(q),x);
	else return kth(rs(q),x-siz(ls(q))-1);
}
void insert(int x){
	int l,r;
	spirit(root,x,l,r);
	root=merge(merge(l,add(x)),r);	
}
void delet(int x){
	int l,r;
	spirit(root,x,l,r);
	int q;
	spirit(l,x-1,l,q);
	q=merge(ls(q),rs(q));
	root=merge(merge(l,q),r);	
}
int ranks(int x){
	int l,r;
	spirit(root,x-1,l,r);
	int ans=siz(l)+1;
	root=merge(l,r);	
	return ans;
}
int pre(int x){
	int l,r;
	spirit(root,x-1,l,r);
	int ans=val(kth(l,siz(l)));
	root=merge(l,r);
	return ans;
}
int nxt(int x){
	int l,r;
	spirit(root,x,l,r);
	int ans=val(kth(r,1));
	root=merge(l,r);	
	return ans;
}
int main(){
	int n;cin>>n;
	while(n--){
		int op,x;cin>>op>>x;
		if(op==1) insert(x);
		else if(op==2) delet(x);
		else if(op==3) cout<<ranks(x)<<"\n";
		else if(op==4) cout<<val(kth(root,x))<<"\n";
		else if(op==5) cout<<pre(x)<<"\n";
		else if(op==6) cout<<nxt(x)<<"\n";
	}
	return 0;
}

P3391 文艺平衡树

  • spirit和merge时记得push_down
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node{
	int val,rans;
	int siz;
	int son[2];
	int tag;
	#define val(q) tree[q].val
	#define rans(q) tree[q].rans
	#define siz(q) tree[q].siz
	#define ls(q) tree[q].son[0]
	#define rs(q) tree[q].son[1]
	#define tag(q) tree[q].tag
}tree[N];
mt19937 rnd(time(0));
int cnt,root;
int add(int x){
	cnt++;
	int q=cnt;
	val(q)=x;
	rans(q)=rnd();
	siz(q)=1;
	ls(q)=rs(q)=0;
	tag(q)=0;
	return q;
}
void into(int q){
	swap(ls(q),rs(q));
	tag(q)^=1;
}
void push_up(int q){
	siz(q)=siz(ls(q))+siz(rs(q))+1;
}
void push_down(int q){
	if(!tag(q)) return ;
	into(ls(q));
	into(rs(q));
	tag(q)=0;
}
void spirit(int q,int x,int &l,int &r){
	if(!q) return l=r=0,void();
	push_down(q);
	if(x<siz(ls(q))+1){
		r=q;
		spirit(ls(q),x,l,ls(q));
	}
	else{
		l=q;
		x-=siz(ls(q))+1;
		spirit(rs(q),x,rs(q),r);
	}
	push_up(q);
}
int merge(int a,int b){
	if(!a||!b) return a+b;
	push_down(a);
	push_down(b);
	if(rans(a)<rans(b)){
		rs(a)=merge(rs(a),b);
		push_up(a);
		return a;
	}
	else{
		ls(b)=merge(a,ls(b));
		push_up(b);
		return b;
	}
}
void dfs(int q){
	push_down(q);
	if(ls(q)) dfs(ls(q));
	cout<<val(q)<<" ";
	if(rs(q)) dfs(rs(q));
}
int main(){
	int n,t;cin>>n>>t;
	for(int i=1;i<=n;i++) root=merge(root,add(i));
	for(int i=1;i<=t;i++){
		int a,b;cin>>a>>b;
		int l,m,r;
		spirit(root,b,l,r);
		spirit(l,a-1,l,m);
		into(m);
		root=merge(merge(l,m),r);
	}
	dfs(root);
	return 0;
}

P3835 可持久化平衡树

  • 在普通平衡树的基础上,在spirit和merge上加新建节点,这里merge新建节点可以省略(spirit已经建过了)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
struct node{
	int val,rans;
	int siz;
	int son[2];
	#define val(q) tree[q].val
	#define rans(q) tree[q].rans
	#define siz(q) tree[q].siz
	#define ls(q) tree[q].son[0]
	#define rs(q) tree[q].son[1]
}tree[N*40];
int cnt=0;int rt[N];
mt19937 rnd(time(0));
int add(int x){
	cnt++;
	int q=cnt;
	val(q)=x;
	rans(q)=rnd();
	siz(q)=1;
	ls(q)=rs(q)=0;
	return cnt;
}
void push_up(int q){
	siz(q)=siz(ls(q))+siz(rs(q))+1;
}
void spirit(int q,int x,int &l,int &r){
	if(!q) return l=r=0,void();
	
	int now=add(1);
	tree[now]=tree[q];
	if(x<val(now)){
		r=now;
		spirit(ls(now),x,l,ls(now));
	}
	else{
		l=now;
		spirit(rs(now),x,rs(now),r);
	}
	push_up(now);
}
int merge(int a,int b){
	if(!a||!b) return a+b;
	if(rans(a)<rans(b)){
		rs(a)=merge(rs(a),b);
		push_up(a);
		return a;
	}
	else{
		ls(b)=merge(a,ls(b));
		push_up(b);
		return b;
	}
}
int kth(int now,int x){
	while(1){
		if(siz(ls(now))+1==x) return now;
		else if(x<=siz(ls(now))) now=ls(now);
		else{
			x-=siz(ls(now))+1;
			now=rs(now);
		}
	}
}
void insert(int v,int i,int x){
	int l,r;
	spirit(rt[v],x,l,r);
	rt[i]=merge(merge(l,add(x)),r);	
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;cin>>n;
	insert(0,0,-2147483647);
	insert(0,0,2147483647);
	for(int i=1;i<=n;i++){
		int v,op,x;cin>>v>>op>>x;
		if(op==1){
			insert(v,i,x);
		}
		else if(op==2){
			int l,r;
			spirit(rt[v],x,l,r);
			int m;
			spirit(l,x-1,l,m);
			if(val(m)==x) m=merge(ls(m),rs(m));
			rt[i]=merge(merge(l,m),r);
		}
		else if(op==3){
			int l,r;
			spirit(rt[v],x-1,l,r);
			cout<<siz(l)<<"\n";
			rt[i]=merge(l,r);
		}
		else if(op==4){
			cout<<val(kth(rt[v],x+1))<<"\n";
			rt[i]=rt[v];
		}
		else if(op==5){
			int l,r;
			spirit(rt[v],x-1,l,r);
			cout<<val(kth(l,siz(l)))<<"\n";
			rt[i]=merge(l,r);
		}
		else if(op==6){
			int l,r;
			spirit(rt[v],x,l,r);
			cout<<val(kth(r,1))<<"\n";
			rt[i]=merge(l,r);
		}
	}
	return 0;
}

P5055 可持久化文艺平衡树

  • push_down时别忘了新建节点
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+10;
struct node{
	int val,rans,siz;
	int son[2];
	LL sum,tag;
	#define val(q) tree[q].val
	#define rans(q) tree[q].rans
	#define siz(q) tree[q].siz
	#define ls(q) tree[q].son[0]
	#define rs(q) tree[q].son[1]
	#define sum(q) tree[q].sum
	#define tag(q) tree[q].tag
}tree[N*80];
int cnt;int rt[N];
mt19937 rnd(time(0));
int add(int x){
	cnt++;
	int q=cnt;
	val(q)=x;
	rans(q)=rnd();
	siz(q)=1;
	ls(q)=rs(q)=0;
	sum(q)=x;
	tag(q)=0;
	return cnt;
}
int cpy(int q){
	cnt++;
	tree[cnt]=tree[q];
	return cnt;
}
void push_up(int q){
	sum(q)=sum(ls(q))+sum(rs(q))+val(q);
	siz(q)=siz(ls(q))+siz(rs(q))+1;
}
void into(int q){
	tag(q)^=1;
	swap(ls(q),rs(q));
}
void push_down(int q){
	if(!tag(q)) return ;
	if(ls(q)) ls(q)=cpy(ls(q));
	if(rs(q)) rs(q)=cpy(rs(q));
	into(ls(q));
	into(rs(q));
	tag(q)=0;
}
void spirit(int las,int x,int &l,int &r){
	if(las==0) return l=r=0,void();
	push_down(las);
	int q=cpy(las);
	
	if(siz(ls(q))+1<=x){
		l=q;
		spirit(rs(q),x-siz(ls(q))-1,rs(q),r);
	}
	else{
		r=q;
		spirit(ls(q),x,l,ls(q));
	}
	push_up(q);
}
int merge(int a,int b){
	if(!a||!b) return a+b;
	push_down(a);
	push_down(b);
	
	int q;
	if(rans(a)<rans(b)){
		q=cpy(a);
		rs(q)=merge(rs(q),b);
	}
	else{
		q=cpy(b);
		ls(q)=merge(a,ls(q));
	}
	push_up(q);
	return q;
}
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;cin>>n;
	LL ans=0;
	for(int i=1;i<=n;i++){
		LL v,op;cin>>v>>op;
		if(op==1){
			LL p,x;cin>>p>>x;p^=ans;x^=ans;
			
			int l,r;
			spirit(rt[v],p,l,r);
			
			rt[i]=merge(merge(l,add(x)),r);
		}
		else if(op==2){
			LL p;cin>>p;p^=ans;
			
			
			int l,r;
			spirit(rt[v],p,l,r);
			int m;
			spirit(l,p-1,l,m);
			m=merge(ls(m),rs(m));
			
			rt[i]=merge(merge(l,m),r);
		}
		else if(op==3){
			LL a,b;cin>>a>>b;a^=ans;b^=ans;
			
			int l,r;
			spirit(rt[v],b,l,r);
			int m;
			spirit(l,a-1,l,m);
			into(m);
			
			rt[i]=merge(merge(l,m),r);
		}
		else{
			LL a,b;cin>>a>>b;a^=ans;b^=ans;
			
			int l,r;
			spirit(rt[v],b,l,r);
			int m;
			spirit(l,a-1,l,m);
			ans=sum(m);
			cout<<ans<<"\n";
			
			rt[i]=rt[v];
		}
	}
	return 0;
}
posted @ 2025-12-31 16:09  Ming3398  阅读(6)  评论(0)    收藏  举报