平衡树
splay
普通平衡树

#include<bits/stdc++.h> using namespace std; const int MAX=101000; char opt; int mi,sum,sm=MAX,num; int son[MAX][2],val[MAX],fa[MAX],siz[MAX],cnt[MAX],tot,root,x,n; inline bool Dir(int x){return val[x]>val[fa[x]];} void pushup(int x){ siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x]; } inline void rotate(int x){ int y=fa[x],z=fa[y],k=Dir(x),w=son[x][k^1]; son[z][Dir(y)]=x;fa[x]=z; son[x][k^1]=y;fa[y]=x; son[y][k]=w;fa[w]=y; pushup(y);pushup(x);//现在y是儿子,x是父亲 } inline void splay(int x,int goal=0){ while(fa[x]!=goal){ int y=fa[x],z=fa[y]; if(z!=goal){ if(Dir(x)==Dir(y)) rotate(y); else rotate(x); }rotate(x); }if(!goal) root=x; //cout<<x<<" "<<siz[root]<<endl; } inline void find(int x){ if(!root) return; int cur=root; while(son[cur][x>val[cur]]&&val[cur]!=x) cur=son[cur][x>val[cur]]; splay(cur); } inline void ins(int x){ int cur=root,p=0; while(cur&&val[cur]!=x) p=cur,cur=son[cur][x>val[cur]]; if(cur) cnt[cur]++; else{ cur=++tot; if(p) son[p][x>val[p]]=cur; son[cur][0]=son[cur][1]=0; val[cur]=x;fa[cur]=p; cnt[cur]=siz[cur]=1; }splay(cur); //cout<<x<<" "<<cur<<endl; } inline int las(int x){ find(x); if(val[root]<x) return root; int cur=son[root][0]; while(son[cur][1]) cur=son[cur][1]; splay(cur);return cur; } inline int nex(int x){ find(x); if(val[root]>x) return root; int cur=son[root][1]; while(son[cur][0]) cur=son[cur][0]; splay(cur);return cur; } inline void del(int x){ int l=las(x),r=nex(x);// splay(l);splay(r,l); int d=son[r][0]; if(cnt[d]>1){cnt[d]--;splay(d);} else son[r][0]=0; pushup(r);pushup(root); } inline int getrk1(int x){ find(x); return siz[son[root][1]]+(val[root]>=x?cnt[root]:0); } inline int getrk(int x){ find(x); return siz[son[root][0]]+(val[root]<x?cnt[root]:0); } inline int getth(int k){ int cur=root; while(1){ if(k<=siz[son[cur][1]]&&son[cur][1]) cur=son[cur][1]; else if(k>siz[son[cur][1]]+cnt[cur]){ k-=siz[son[cur][1]]+cnt[cur]; cur=son[cur][0]; } else{splay(cur);return val[cur];} } }
艺术平衡树

#include<bits/stdc++.h> using namespace std; const int MAX=100010; int son[MAX][2],siz[MAX],val[MAX],fa[MAX],laz[MAX],tot,root,m,n,x,a[MAX]; inline 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<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } inline bool Dir(int x){return x==son[fa[x]][1];}//val[x]>val[fa[x]]不具有左小右大 inline void pushup(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;} inline void pushdown(int x){ if(x&&laz[x]){ laz[son[x][0]]^=1;laz[son[x][1]]^=1; swap(son[x][0],son[x][1]);laz[x]=0; } } int build(int f,int l,int r){ if(l>r) return 0; int mid=(l+r)>>1,cur=++tot; son[cur][0]=son[cur][1]=0; val[cur]=a[mid];fa[cur]=f;laz[cur]=0;//cur son[cur][0]=build(cur,l,mid-1);//避开重复祖先 son[cur][1]=build(cur,mid+1,r); pushup(cur);return cur; } void write(int x){ pushdown(x); if(son[x][0]) write(son[x][0]); if(abs(val[x])!=INT_MAX) printf("%d ",val[x]); if(son[x][1]) write(son[x][1]); } inline void rotate(int x){ int y=fa[x],z=fa[y],k=Dir(x),w=son[x][k^1]; pushdown(y);pushdown(x); son[z][Dir(y)]=x;fa[x]=z; son[x][k^1]=y;fa[y]=x; son[y][k]=w;fa[w]=y; pushup(y),pushup(x); } inline void splay(int x,int goal=0){ while(fa[x]!=goal){ int y=fa[x],z=fa[y]; if(z!=goal){ if(Dir(x)==Dir(y)) rotate(y); else rotate(x); }rotate(x); }if(!goal) root=x; } inline int getth(int k){ int cur=root; while(1){ pushdown(cur); if(k>siz[son[cur][0]]){ k-=siz[son[cur][0]]+1; if(!k) return cur; cur=son[cur][1]; }else cur=son[cur][0]; } } inline void turn(int l,int r){ l=getth(l);r=getth(r+2); splay(l);splay(r,l); laz[son[son[root][1]][0]]^=1; } int main(){ n=read();m=read(); a[1]=-INT_MAX;a[n+2]=INT_MAX; for(int i=2;i<=n+1;++i) a[i]=i-1; root=build(0,1,n+2); for(int i=1;i<=m;++i){int l=read(),r=read();turn(l,r);} write(root); }
二逼平衡树

#include<bits/stdc++.h> using namespace std; const int MAX=50010<<5; int k,mi=INT_MAX,ma=-INT_MAX; int son[MAX][2],siz[MAX],val[MAX],fa[MAX],cnt[MAX],tot,root[MAX],m,n,x,a[MAX],opt,l,r; inline 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<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } void build(int,int,int); int query1(int,int,int,int,int,int); int query2(int,int,int,int,int,int); int query3(int,int,int,int,int,int); void update(int,int,int,int,int); inline bool Dir(int x){return val[x]>val[fa[x]];} void pushup(int x){ siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x]; } inline void rotate(int x){ int y=fa[x],z=fa[y],k=Dir(x),w=son[x][k^1]; son[z][Dir(y)]=x;fa[x]=z; son[x][k^1]=y;fa[y]=x; son[y][k]=w;fa[w]=y; pushup(y);pushup(x); } inline void splay(int pos,int x,int goal=0){ while(fa[x]!=goal){ int y=fa[x],z=fa[y]; if(z!=goal){ if(Dir(x)==Dir(y)) rotate(y); else rotate(x); }rotate(x); }if(!goal) root[pos]=x; } inline void ins(int pos,int x){ int cur=root[pos],p=0; while(cur&&val[cur]!=x) p=cur,cur=son[cur][x>val[cur]]; if(cur) cnt[cur]++; else{ cur=++tot;son[p][x>val[p]]=cur; val[cur]=x;fa[cur]=p; cnt[cur]=siz[cur]=1; }splay(pos,cur); } inline void find(int pos,int x){ int cur=root[pos]; while(son[cur][x>val[cur]]&&val[cur]!=x) cur=son[cur][x>val[cur]]; splay(pos,cur); } inline int getrk(int pos,int x){ find(pos,x); return siz[son[root[pos]][0]]+(val[root[pos]]<x?cnt[root[pos]]:0); } inline int las(int pos,int x){ find(pos,x); if(val[root[pos]]<x) return root[pos]; int cur=son[root[pos]][0]; while(son[cur][1]) cur=son[cur][1]; splay(pos,cur);return cur; } inline int nex(int pos,int x){ find(pos,x); if(val[root[pos]]>x) return root[pos]; int cur=son[root[pos]][1]; while(son[cur][0]) cur=son[cur][0]; splay(pos,cur);return cur; } inline void del(int pos,int x){ int l=las(pos,x),r=nex(pos,x); splay(pos,l);splay(pos,r,l); int d=son[r][0]; if(cnt[d]>1){cnt[d]--;splay(pos,d);} else son[r][0]=0; pushup(r);pushup(root[pos]); } int main(){ n=read();m=read(); for(int i=1;i<=n;++i) a[i]=read(),mi=min(mi,a[i]),ma=max(ma,a[i]); build(1,1,n); for(int i=1;i<=m;++i){ opt=read(); if(opt==1){ l=read();r=read();x=read(); printf("%d\n",query1(1,1,n,l,r,x)+1); } if(opt==2){ l=read();r=read();k=read(); int ll=mi,rr=ma,ans; while(ll<rr){ int mid=(ll+rr)>>1; int rk=query1(1,1,n,l,r,mid)+1,r1=query1(1,1,n,l,r,mid+1); if(rk<=k&&r1>=k){ans=mid;break;} if(rk>k) rr=mid; else ll=mid+1; }printf("%d\n",ans); } if(opt==3){ k=read();x=read(); mi=min(mi,x);ma=max(ma,x); update(1,1,n,k,x); } if(opt==4){ l=read();r=read();x=read(); printf("%d\n",query2(1,1,n,l,r,x)); } if(opt==5){ l=read();r=read();x=read(); printf("%d\n",query3(1,1,n,l,r,x)); } } } void build(int pos,int l,int r){ if(r<l) return; ins(pos,-INT_MAX);ins(pos,INT_MAX); for(int i=l;i<=r;++i) ins(pos,a[i]); if(l==r) return; int mid=(l+r)>>1; build(pos<<1,l,mid);build(pos<<1|1,mid+1,r); } int query1(int pos,int l,int r,int ll,int rr,int x){ if(l>rr||r<ll) return 0; if(ll<=l&&r<=rr) return getrk(pos,x)-1; int mid=(l+r)>>1; return query1(pos<<1,l,mid,ll,rr,x)+query1(pos<<1|1,mid+1,r,ll,rr,x); } void update(int pos,int l,int r,int k,int x){ if(k<l||k>r) return; del(pos,a[k]);ins(pos,x); if(l==r){a[k]=x;return;} int mid=(l+r)>>1; if(k<=mid) update(pos<<1,l,mid,k,x); else update(pos<<1|1,mid+1,r,k,x); } int query2(int pos,int l,int r,int ll,int rr,int x){ if(l>rr||r<ll) return -INT_MAX; if(ll<=l&&r<=rr) return val[las(pos,x)]; int mid=(l+r)>>1; return max(query2(pos<<1,l,mid,ll,rr,x),query2(pos<<1|1,mid+1,r,ll,rr,x)); } int query3(int pos,int l,int r,int ll,int rr,int x){ if(l>rr||r<ll) return INT_MAX; if(ll<=l&&r<=rr) return val[nex(pos,x)]; int mid=(l+r)>>1; return min(query3(pos<<1,l,mid,ll,rr,x),query3(pos<<1|1,mid+1,r,ll,rr,x)); }
treap
旋转

#include<bits/stdc++.h> using namespace std; #define ls son[cur][0] #define rs son[cur][1] const int MAX=100010; int n,x,opt; int rd[MAX],son[MAX][2],siz[MAX],cnt[MAX],val[MAX],root,tot; inline 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<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } inline int rand(){ static int seed=2007; return seed=(int)((((seed^213)+130183)*1583098ll)%14585428ll); } inline void pushup(int cur){siz[cur]=siz[ls]+siz[rs]+cnt[cur];} inline void rotate(int &x,int dir){ int r=son[x][dir];son[x][dir]=son[t][dir^1]; son[t][dir^1]=x;pushup(x);pushup(t);x=t; } void ins(int &cur,int x){ if(!cur){ cur=++tot;siz[cur]=cnt[cur]=1; val[cur]=x;rn[cur]=rand();return; }siz[cur]++; if(val[cur]==x) cnt[cur]++; else if(x>val[cur]){ ins(rs,x); if(rn[rs]<rn[cur]) rotate(cur,(x>val[cur])); }else{ ins(ls,x); if(rn[ls<rn[cur]]) rotate(cur,(x>val[cur])); } } void del(int &cur,int x){ if(!cur) return; if(val[cur]==x){ if(cnt[cur]>1) cnt[cur]--,siz[cur]--; else{ if((!ls)||(!rs)) cur=ls+rs; else rotate(cur,(ls>=rs)),dal(cur,x); } }else siz[cur]--,del(son[cur][x>val[cur]],x); } int getrk(int x){ int cur=root,ans=0; while(cur){ if(x<val[cur]) cur=ls; else if(x>val[cur]){ ans+=siz[ls]+cnt[cur];cur=rs; }else return ans+siz[ls]+1; }return ans+1; } int getth(int k){ int cur=root; while(cur){ if(k<=siz[ls]) cur=ls; else if(k>siz[ls]+cnt[cur]){ k-=siz[ls]+cnt[cur];cur=rs; }else return val[cur]; }return 0; } int las(int x){ int cur=root,ans=-1; while(cur){ if(x>val[cur]) ans=val[cur],cur=rs; else cur=ls; }return ans; } int nex(int x){ int cur=root,ans=-1; while(cur){ if(x<val[cur]) ans=val[cur],cur=ls; else cur=rs; }return ans; }
无旋/FHQ

inline int get(int x){ t[++tot]={0,0,x,rand(),1};return tot; }inline void pushup(int pos){t[pos].siz=t[t[pos].l].siz+t[t[pos].r].siz;} void split(int pos,int x,int &l,int &r){ if(!pos){l=r=0;return;} if(t[pos].key<=x){l=pos;split(t[l].r,x,t[l].r,r);} else{r=pos;split(t[r].l,x,l,r[r].l);} pushup(pos); }int merge(int l,int r){ if(!l||!r) return l|r; if(t[l].val<=t[r].val){ t[l].r=merge(t[l].r,r); pushup(l);return l; }t[r].l=merge(l,t[r].l); pushup(r);return r; }inline void insert(int x){ split(rt,x-1,dl,dr);rt=merge(merge(dl,get(x)),dr); }inline void del(int x){ split(rt,x-1,dl,dr);split(dr,x,tmp,dr); tmp=merge(t[tmp].l,t[tmp].r);rt=merge(merge(dl,tmp),dr); }inline int getrk(int x){ split(rt,x-1,dl,dr);int rk=t[dl].size+1; rt=merge(dl,dr);return rk; }int getnum(int pos,int x){ int num=t[t[pos].l].siz+1; if(num==x) return t[pos].key; if(num>x) return getnum(t[pos].l,x); return getnum(t[pos].r,x-num); }inline int pre(int x){ split(rt,x-1,dl,dr); int num=getnum(dl,t[dl].siz); rt=merge(dl,dr);return num; }inline int nxt(int x){ split(rt,x,dl,dr); int num=getnum(dr,1); rt=merge(dl,dr);return num; }
可持久化
只是在split复制了节点

#include<bits/stdc++.h> using namespace std; const int MAX=5e5+10; const int inf=(1ll<<31)-1; int n,rt[MAX],i,tot,dl,dr,tmp,v,opt,x; struct node{ int l,r,key,val,siz; } t[MAX*50]; inline 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<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } inline int get(int x){ t[++tot]={0,0,x,rand(),1};return tot; }inline void pushup(int pos){t[pos].siz=t[t[pos].l].siz+t[t[pos].r].siz+1;} void split(int pos,int x,int &l,int &r){ if(!pos){l=r=0;return;} int now=++tot;t[now]=t[pos]; if(t[now].key<=x){l=now;split(t[l].r,x,t[l].r,r);} else{r=now;split(t[r].l,x,l,t[r].l);} pushup(now); }int merge(int l,int r){ if(!l||!r) return l|r; if(t[l].val<=t[r].val){ t[l].r=merge(t[l].r,r); pushup(l);return l; }t[r].l=merge(l,t[r].l); pushup(r);return r; }inline void insert(int x){ split(rt[i],x-1,dl,dr);rt[i]=merge(merge(dl,get(x)),dr); }inline void del(int x){ split(rt[i],x-1,dl,dr);split(dr,x,tmp,dr); tmp=merge(t[tmp].l,t[tmp].r);rt[i]=merge(merge(dl,tmp),dr); }inline int getrk(int x){ split(rt[i],x-1,dl,dr);int rk=t[dl].siz; rt[i]=merge(dl,dr);return rk; }int getnum(int pos,int x){ int num=t[t[pos].l].siz+1; if(num==x) return t[pos].key; if(num>x) return getnum(t[pos].l,x); return getnum(t[pos].r,x-num); }inline int pre(int x){ split(rt[i],x-1,dl,dr); int num=getnum(dl,t[dl].siz); rt[i]=merge(dl,dr);return num; }inline int nxt(int x){ split(rt[i],x,dl,dr); int num=getnum(dr,1); rt[i]=merge(dl,dr);return num; } signed main(){ n=read(); insert(inf);insert(-inf); for(i=1;i<=n;++i){ v=read();opt=read();x=read(); rt[i]=rt[v]; if(opt==1) insert(x); if(opt==2) del(x); if(opt==3) printf("%d\n",getrk(x)); if(opt==4) printf("%d\n",getnum(rt[i],x+1)); if(opt==5) printf("%d\n",pre(x)); if(opt==6) printf("%d\n",nxt(x)); } }
在merge中也复制节点。在下放标记时可以省略split

#include<bits/stdc++.h> using namespace std; const int MAX=5e5+10; const int inf=(1ll<<31)-1; int n,rt[MAX],i,tot,dl,dr,tmp,v,opt,x; struct node{ int l,r,key,val,siz; } t[MAX*50]; inline 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<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } inline int get(int x){ t[++tot]={0,0,x,rand(),1};return tot; }inline void pushup(int pos){t[pos].siz=t[t[pos].l].siz+t[t[pos].r].siz+1;} void split(int pos,int x,int &l,int &r){ if(!pos){l=r=0;return;} int now=++tot;t[now]=t[pos]; if(t[now].key<=x){l=now;split(t[l].r,x,t[l].r,r);} else{r=now;split(t[r].l,x,l,t[r].l);} pushup(now); }int merge(int l,int r){ if(!l||!r) return l|r; int now=++tot; if(t[l].val<=t[r].val){ t[now]=t[l]; t[now].r=merge(t[now].r,r); }else{t[now]=t[r];t[now].l=merge(l,t[now].l);} pushup(now);return now; }inline void insert(int x){ split(rt[i],x-1,dl,dr);rt[i]=merge(merge(dl,get(x)),dr); }inline void del(int x){ split(rt[i],x-1,dl,dr);split(dr,x,tmp,dr); tmp=merge(t[tmp].l,t[tmp].r);rt[i]=merge(merge(dl,tmp),dr); }inline int getrk(int x){ split(rt[i],x-1,dl,dr);int rk=t[dl].siz; rt[i]=merge(dl,dr);return rk; }int getnum(int pos,int x){ int num=t[t[pos].l].siz+1; if(num==x) return t[pos].key; if(num>x) return getnum(t[pos].l,x); return getnum(t[pos].r,x-num); }inline int pre(int x){ split(rt[i],x-1,dl,dr); int num=getnum(dl,t[dl].siz); rt[i]=merge(dl,dr);return num; }inline int nxt(int x){ split(rt[i],x,dl,dr); int num=getnum(dr,1); rt[i]=merge(dl,dr);return num; } signed main(){ n=read(); insert(inf);insert(-inf); for(i=1;i<=n;++i){ v=read();opt=read();x=read(); rt[i]=rt[v]; if(opt==1) insert(x); if(opt==2) del(x); if(opt==3) printf("%d\n",getrk(x)); if(opt==4) printf("%d\n",getnum(rt[i],x+1)); if(opt==5) printf("%d\n",pre(x)); if(opt==6) printf("%d\n",nxt(x)); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律