平衡树模板

Treap

通过维护堆的性质,使平衡树平衡,操作是旋转。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2022,inf=0x3f3f3f3f; 
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
struct node{
	int l,r,val,num,size,rnd;
}e[N];
int t,opt,vv,cnt,root;
void newnode(int val){
	cnt++;
	e[cnt].rnd=rand()*32767+rand();
	e[cnt].num=e[cnt].size=1;
	e[cnt].val=val;
	return;
}
void pushup(int u){
	e[u].size=e[e[u].l].size+e[e[u].r].size+e[u].num;
	return;
} 
void zag(int &u){
	int x=e[u].r;
	e[u].r=e[x].l;
	e[x].l=u;
	u=x;
	pushup(e[u].l),pushup(u);
	return;
}
void zig(int &u){
	int x=e[u].l;
	e[u].l=e[x].r;
	e[x].r=u;
	u=x;
	pushup(e[u].r),pushup(u);
	return;
}
void insert(int &u,int key){
	if(!u){
		newnode(key),u=cnt;
		return;	
	}
	if(e[u].val==key)e[u].num++;
	if(key<e[u].val){
		insert(e[u].l,key);
		if(e[u].rnd<e[e[u].l].rnd)zig(u);
	}
	if(key>e[u].val){
		insert(e[u].r,key);
		if(e[u].rnd<e[e[u].r].rnd)zag(u);
	}
	pushup(u);
	return;
}
void erase(int &u,int key){
	if(!u)return;
	if(e[u].val==key){
		if(e[u].num>1)e[u].num--;
		else{
			if(!e[u].l)u=e[u].r;
			else if(!e[u].r)u=e[u].l;
			else if(e[e[u].l].rnd>e[e[u].r].rnd){
				zig(u);
				erase(e[u].r,key);
			}
			else{
				zag(u);
				erase(e[u].l,key);
			}
		}
	}
	else if(key<e[u].val)erase(e[u].l,key);
	else if(key>e[u].val)erase(e[u].r,key);
	pushup(u);
	return;
}
int get_rank(int u,int key){
	if(!u)return 0;
	if(e[u].val==key)return e[e[u].l].size;
	if(key<e[u].val)return get_rank(e[u].l,key);
	if(key>e[u].val)return e[e[u].l].size+e[u].num+get_rank(e[u].r,key);
}
int get_val(int u,int key){
	if(!u)return 0;
	if(e[e[u].l].size>=key)return get_val(e[u].l,key);
	if(e[e[u].l].size+e[u].num>=key)return e[u].val;
	return get_val(e[u].r,key-e[u].num-e[e[u].l].size); 
}
int get_pre(int u,int key){
	 if(!u)return -inf;
	 if(key<=e[u].val)return get_pre(e[u].l,key);
	 else return max(e[u].val,get_pre(e[u].r,key));
} 
int get_nxt(int u,int key){
	 if(!u)return inf;
	 if(key>=e[u].val)return get_nxt(e[u].r,key);
	 else return min(e[u].val,get_nxt(e[u].l,key));
} 
int main(){
	srand(time(NULL));
	newnode(-inf);
	newnode(inf);
	e[1].r=2;
	e[1].size=2;
	root=1;
	if(e[1].rnd<e[2].rnd)zag(root);
	
	t=read();
	while(t--){
		opt=read(),vv=read();
		if(opt==1)insert(root,vv); 
		if(opt==2)erase(root,vv);
		if(opt==3)printf("%d\n",get_rank(root,vv));
		if(opt==4)printf("%d\n",get_val(root,vv+1));
		if(opt==5)printf("%d\n",get_pre(root,vv));
		if(opt==6)printf("%d\n",get_nxt(root,vv)); 
	}
	return 0;
}

Splay

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2022; 
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
struct node{
	int ch[2],v,lazy,size,fa;
}tr[N];
int n,m,root,tot;
int newnode(int p,int v){
	tr[++tot].v=v;
	tr[tot].fa=p;
	tr[tot].size=1;
	return tot; 
} 
void pushup(int u){
	tr[u].size=1+tr[tr[u].ch[0]].size+tr[tr[u].ch[1]].size;
	return;
}
void rotate(int x){
	int y=tr[x].fa,z=tr[y].fa;
	int k=(tr[y].ch[1]==x);
	tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa=z;
	tr[y].ch[k]=tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa=y;
	tr[x].ch[k^1]=z,tr[z].fa=x;
	pushup(y),pushup(x);
	return;
}
void pushdown(int u){
	if(tr[u].lazy){
		swap(tr[u].ch[0],tr[u].ch[1]);
		tr[u].lazy=0;
		tr[tr[u].ch[0]].lazy^=1;
		tr[tr[u].ch[1]].lazy^=1;
	}
	return;
} 
void print(int u){
	pushdown(u);
	if(tr[u].ch[0])print(tr[u].ch[0]);
	if(tr[u].v!=0 && tr[u].v!=n+1)printf("%d ",tr[u].v);
	if(tr[u].ch[0])print(tr[u].ch[1]);
	return; 
} 
void splay(int x,int k){
	while(tr[x].fa!=k){
		int y=tr[x].fa,z=tr[y].fa;
		if(z!=k){
			if((tr[y].ch[1]==x)!=(tr[z].ch[1]==y)) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
	if(!k)root=x;
	return;
}
int get_k(int k){
	int u=root;
	while(1){
		pushdown(u);
		if(tr[tr[u].ch[0]].size>=k)u=tr[u].ch[0];
		else if(tr[tr[u].ch[0]].size+1==k)return u;
		else k-=tr[tr[u].ch[0]].size+1,u=tr[u].ch[1];
	}
}
void insert(int p,int v){
	if(!tr[p].ch[v>tr[p].v])tr[p].ch[v>tr[p].v]=newnode(p,v);
	else insert(tr[p].ch[v>tr[p].v],v);
	return;
}
void ts(int u){
	cout<<u<<" "<<tr[u].ch[0]<<" "<<tr[u].ch[1]<<endl;
	if(tr[u].ch[0])ts(tr[u].ch[0]);
	if(tr[u].ch[1])ts(tr[u].ch[1]);
	return;
}
int main(){
	n=read(),m=read();
	for(int i=0;i<n+2;i++){
		insert(root,i);
		splay(tot,0);
		ts(root);
		cout<<endl;
	}
	while(m--){
		int L,R,l,r;
		l=read(),r=read();
		L=get_k(l),R=get_k(r+2);
		splay(L,0),splay(R,L);
		tr[tr[R].ch[0]].lazy^=1;
	}
	print(root);
	return 0;
} 

FHQ Treap

学会分裂合并,你将不用旋转。

合并的时候注意顺序,merge(A,B)是合并成A在B的前面。
还有注意pushup的位置,别把0号点pushup了。

事实上他很适合处理区间问题,因为他的中序遍历就是原序列(废话),要处理一个区间只需要暴力split这个区间即可。

l=read(),r=read();
split(rt,l-1,x,y);
split(y,r-l+1,y,z);
e[y].lazy^=1;//这是区间上的操作
rt=merge(merge(x,y),z);

CODE

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,opt,x,y,cnt,rt,z;
struct node{
	int val,rad,size;
}e[N];
int ls[N],rs[N];
void pushup(int u){e[u].size=e[ls[u]].size+e[rs[u]].size+1;return;}
void split(int u,int val,int &x,int &y){
	if(!u)x=y=0;
	else{
		if(e[u].val<=val)x=u,split(rs[u],val,rs[u],y);
		else y=u,split(ls[u],val,x,ls[u]);
		pushup(u);
	}
	return;
}
//split也可以按排名分裂 
/*
void split(int u,int k,int &x,int &y){
	if(!u)x=0,y=0;
	else{
		if(k>e[ls[u]].size){x=u,split(rs[u],k-e[ls[u]].size-1,rs[u],y);}
		else{y=u,split(ls[u],k,x,ls[y]);}
		pushup(u);
	}
	return;
}
*/
int merge(int A,int B){
	if(!A || !B)return A+B;
	if(e[A].rad<e[B].rad){rs[A]=merge(rs[A],B);pushup(A);return A;}
	else {ls[B]=merge(A,ls[B]);pushup(B);return B;}
}
int newnode(int val){
	e[++cnt].rad=rand()*32767+rand();
	e[cnt].val=val;
	e[cnt].size=1;
	return cnt;
}
void insert(int val){
	split(rt,val,x,y);
	rt=merge(merge(x,newnode(val)),y);
	return;
}
void erase(int val){
	split(rt,val,x,z);
	split(x,val-1,x,y);
	y=merge(ls[y],rs[y]);
	rt=merge(merge(x,y),z);
	return;
}
int get_rank(int val){
	split(rt,val-1,x,y);
	int tmp=e[x].size+1;
	rt=merge(x,y);
	return tmp;
}
int kth(int u,int k){
	if(!u)return 0;
	if(k<=e[ls[u]].size)return kth(ls[u],k);
	if(k<=e[ls[u]].size+1)return u;
	return kth(rs[u],k-1-e[ls[u]].size);
}
int pre(int val){
	split(rt,val-1,x,y);
	int tmp=kth(x,e[x].size);
	rt=merge(x,y);
	return e[tmp].val;
}

int nxt(int val){
	split(rt,val,x,y);
	int tmp=kth(y,1);
	rt=merge(x,y);
	return e[tmp].val;
}

int main(){
	srand('F'+'H'+'Q'+'Y'+'Y'+'D'+'S');
	n=read();
	for(int i=1;i<=n;i++){
		opt=read();
		if(opt==1)insert(read());
		if(opt==2)erase(read());
		if(opt==3)printf("%d\n",get_rank(read()));
		if(opt==4)printf("%d\n",e[kth(rt,read())].val);
		if(opt==5)printf("%d\n",pre(read()));
		if(opt==6)printf("%d\n",nxt(read()));
	}
	return 0;
} 

文艺平衡树

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+110;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();} 
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int rt,cnt,x,y,z,ls[N],rs[N];
struct node{
	int val,rad,size,lazy;
}e[N];
int n,m;
void pushup(int u){e[u].size=1+e[ls[u]].size+e[rs[u]].size;return;}
int newnode(){e[++cnt].rad=rand(); e[cnt].size=1;return cnt;}
void pushdown(int u){
	if(e[u].lazy){
		swap(ls[u],rs[u]);e[ls[u]].lazy^=1,e[rs[u]].lazy^=1;
		e[u].lazy=0;
	}
	return;
}
void split(int u,int k,int &x,int &y){
	if(!u)x=0,y=0;
    pushdown(u);//pushdown标记
	else{
		if(k>e[ls[u]].size){pushdown(x);x=u,split(rs[u],k-e[ls[u]].size-1,rs[u],y);}
		else{pushdown(y);y=u,split(ls[u],k,x,ls[y]);}
		pushup(u);
	}
	return;
}
int merge(int A,int B){
	if(!A || !B)return A+B;
	if(e[A].rad<e[B].rad){pushdown(A);rs[A]=merge(rs[A],B);pushup(A);return A;}
	else{pushdown(B);ls[B]=merge(A,ls[B]);pushup(B);return B;}
    //别忘记pushdown
} 
void insert(int k){
	split(rt,k,x,y);
	rt=merge(merge(x,newnode()),y);
	return;
}
void print(int u){
	if(!u)return;
	pushdown(u);
	print(ls[u]); 
	printf("%d ",u);
	print(rs[u]);
	return;
} 
int main(){
	srand('F'+'J');int l,r;
	n=read(),m=read();
	for(int i=1;i<=n;i++)insert(i-1);
	for(int i=1;i<=m;i++){
		l=read(),r=read();
		split(rt,l-1,x,y);
		split(y,r-l+1,y,z);
		e[y].lazy^=1;
		rt=merge(merge(x,y),z);
	}
	print(rt);
	return 0;
}

可持久化文艺平衡树

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4e5*50;
int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();} 
    while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
struct node{
    int val,rad,size,lazy;ll sum;
}e[N];
int ls[N],rs[N],rt[N],cnt,x,y,z;
int dust[N],bin;//垃圾回收:删掉的点重新用

int newnode(int val){
    int xv=bin?dust[bin--]:++cnt;
    e[xv].rad=rand();
    e[xv].val=val;
    e[xv].sum=val;
    e[xv].size=1;
    ls[xv]=0;
	rs[xv]=0; 
    return xv;
}
int clone(int u){
    int xv=bin?dust[bin--]:++cnt;
    e[xv].rad=e[u].rad;//不复制会MLE?WHY? 
    e[xv].val=e[u].val;
    e[xv].sum=e[u].sum;
    e[xv].size=e[u].size;
    e[xv].lazy=e[u].lazy;//lazy没复制卡了我5h 
    ls[xv]=ls[u];
    rs[xv]=rs[u];
    return xv;
}
void pushdown(int u){
    if(e[u].lazy){
        swap(ls[u],rs[u]);
        if(ls[u]){ls[u]=clone(ls[u]);e[ls[u]].lazy^=1;}
        if(rs[u]){rs[u]=clone(rs[u]);e[rs[u]].lazy^=1;}
        e[u].lazy=0;
    } 
    return;
}
void pushup(int u){
    e[u].size=1+e[ls[u]].size+e[rs[u]].size;
    e[u].sum=(ll)e[u].val+e[ls[u]].sum+e[rs[u]].sum; 
    return;
}
void split(int u,int k,int &x,int &y){
    if(!u)x=y=0;
    else{
        pushdown(u);
        if(k>e[ls[u]].size){
            x=clone(u);//不一样的地方
            split(rs[x],k-1-e[ls[u]].size,rs[x],y);
            pushup(x);
        }
        else{
            y=clone(u);
            split(ls[y],k,x,ls[y]);
            pushup(y);
        }
    }
    return;
}
int merge(int A,int B){
    if(!A || !B)return A+B;
    else{
        if(e[A].rad<e[B].rad){
            pushdown(A);
            rs[A]=merge(rs[A],B);
            pushup(A);
            return A;
        }
        else{
            pushdown(B);
            ls[B]=merge(A,ls[B]);
            pushup(B);
            return B;
        }
    }
}
void insert(int &u,int k,int val){
    split(u,k,x,y);
    u=merge(merge(x,newnode(val)),y);
    return;
} 
void erase(int &u,int k){
    split(u,k-1,x,y);
    split(y,1,y,z);
    dust[++bin]=y;
    u=merge(x,z);
    return;
}
void revise(int &u,int l,int r){//别忘记u要传值
    split(u,l-1,x,y);
    split(y,r-l+1,y,z);
    e[y].lazy^=1;
    u=merge(merge(x,y),z);
    return;
}
ll query(int &u,int l,int r){
    split(u,l-1,x,y);
    split(y,r-l+1,y,z);
    ll res=e[y].sum;
    u=merge(merge(x,y),z);
    return res;
}
int n,l,r,v,opt;ll lastans;
int main(){
    srand(114514);n=read();//垃圾种子
    for(int i=1;i<=n;i++){
        v=read();opt=read();
        rt[i]=rt[v];
        if(opt==1){
            l=read(),r=read();
            l^=lastans,r^=lastans;
            insert(rt[i],l,r);
        } 
        if(opt==2){
            l=read();l^=lastans;
            erase(rt[i],l);
        }
        if(opt==3){
            l=read(),r=read();
            l^=lastans,r^=lastans;
            if(l>r)swap(l,r);//额。。。
            revise(rt[i],l,r);
        }
        if(opt==4){

            l=read(),r=read();
            l^=lastans,r^=lastans;
            if(l>r)swap(l,r);
            lastans=query(rt[i],l,r);
            printf("%lld\n",lastans);//long long
        }
    } 
    return 0;
} 

可持久化平衡树

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5*50;
int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();} 
    while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
struct node{
    int val,rad,size;
}e[N];
int ls[N],rs[N],rt[N],cnt,x,y,z,n;

int newnode(int val){
    int xv=++cnt;
    e[xv].rad=rand(),e[xv].val=val,e[xv].size=1;ls[xv]=0,rs[xv]=0;
    return xv;
}
void pushup(int u){e[u].size=1+e[ls[u]].size+e[rs[u]].size;return;}
int clone(int u){
    int xv=++cnt;
    e[xv]=e[u];ls[xv]=ls[u];rs[xv]=rs[u];
    return xv;
}
void split(int u,int val,int &x,int &y){
    if(!u)x=y=0;
    else{
        if(e[u].val<=val){x=clone(u);split(rs[x],val,rs[x],y);pushup(x);}
        else{y=clone(u);split(ls[y],val,x,ls[y]);pushup(y);}
    }
    return;
}
int merge(int A,int B){
    if(!A || !B)return A+B;
    else{
        if(e[A].rad<e[B].rad){
            int tmp=clone(A);
            rs[tmp]=merge(rs[tmp],B);
            pushup(tmp);
            return tmp;
        }
        else{
            int tmp=clone(B);
            ls[tmp]=merge(A,ls[tmp]);
            pushup(tmp);
            return tmp;
        }
    }
}
void insert(int &u,int val){
    split(u,val,x,y);
    u=merge(merge(x,newnode(val)),y);
    return;
}
void erase(int &u,int val){
    split(u,val,x,z);
    split(x,val-1,x,y);
    y=merge(ls[y],rs[y]); 
    u=merge(merge(x,y),z);
    return;
}
int get_rank(int u,int val){
    if(!u)return 0;
    if(val<e[u].val)return get_rank(ls[u],val);
    if(val==e[u].val)return e[ls[u]].size+get_rank(rs[u],val);
    if(val>e[u].val)return 1+e[ls[u]].size+get_rank(rs[u],val);
}
int kth(int u,int k){
    if(!u)return 0;
    if(k<=e[ls[u]].size)return kth(ls[u],k);
    if(k<=e[ls[u]].size+1)return u;
    return kth(rs[u],k-1-e[ls[u]].size);
}
int pre(int &u,int val){
    split(u,val-1,x,y);
    int tmp=kth(x,e[x].size);
    u=merge(x,y);
    return e[tmp].val;
}
int nxt(int &u,int val){
    split(u,val,x,y);
    int tmp=kth(y,1);
    u=merge(x,y);
    return e[tmp].val;
}
signed main(){ 
    int seed='L'+'J'+'P'+'i'+'n'+'g'+'H'+'e'+'n'+'g'+'S'+'h'+'u'+'H'+'u'+'i'+'W'+'o'+'Q'+'i'+'n'+'g'+'C'+'h'+'u'+'n';srand(seed); 
    n=read();int v,opt,val,k;
    insert(rt[0],-2147483647);insert(rt[0],2147483647);
    for(int i=1;i<=n;i++){
        v=read(),opt=read();rt[i]=rt[v];
        if(opt==1){val=read();insert(rt[i],val);}
        if(opt==2){val=read();erase(rt[i],val);}
        if(opt==3){val=read();printf("%d\n",get_rank(rt[i],val))-1;}
        if(opt==4){k=read();printf("%d\n",e[kth(rt[i],k+1)].val);}
        if(opt==5){val=read();printf("%d\n",pre(rt[i],val));} 
        if(opt==6){val=read();printf("%d\n",nxt(rt[i],val));}
    }
    return 0;
}
posted @   FJOI  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示