各种平衡树板子
平衡树:
Splay
#include <bits/stdc++.h> #define root T[0].son[1] using namespace std; int read() { int re = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') {if (ch == '-') f = -f; ch = getchar();} while ('0' <= ch && ch <= '9') {re = re * 10 + ch - '0'; ch = getchar();} return re * f; } const int N = 1e5 + 3; const int INF = 1e7 + 3; int n, cnt; struct node{ int v,recy,sum;//权值 重复个数 子树总个数 int fa,son[2];//爹 儿子 }T[N]; void pushup(int x){//更新大小 T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+T[x].recy; } bool identify(int x){//确定父子关系 return T[T[x].fa].son[0]==x?0:1; } void connect(int x,int fa,int son){//认亲 T[x].fa=fa; T[fa].son[son]=x; } void rotate(int x){//旋转 int y=T[x].fa; int z=T[y].fa; int zson=identify(y); int yson=identify(x); int xson=T[x].son[yson^1]; connect(xson,y,yson); connect(y,x,yson^1); connect(x,z,zson); pushup(y); pushup(x); return ; } void splay(int x,int to){//移动x到to的位置 int tofa=T[to].fa; while(tofa!=T[x].fa){ int fa=T[x].fa; int gfa=T[fa].fa; if(gfa!=tofa){ if(identify(x)!=identify(fa)){ rotate(x); }else{ rotate(fa); } } rotate(x); } if(to==root){ root=x; } } int newpoint(int v,int fa){//建新点 T[++cnt].fa=fa; T[cnt].v=v; T[cnt].sum=T[cnt].recy=1; return cnt; } void Insert(int v){//插入权值为v的点 int now=root; if(!root){root=newpoint(v,0);} else{ while(1){ T[now].sum++; if(T[now].v==v){ T[now].recy++; splay(now,root); return; } int next=T[now].v<v?1:0; if(!T[now].son[next]){ T[now].son[next]=newpoint(v,now); splay(cnt,root); return; } now=T[now].son[next]; } } } int find(int v){//查询权值为v的点在的位置 int now=root; while(1){ if(T[now].v==v){ splay(now,root); return now; } int next=T[now].v<v?1:0; if(!T[now].son[next]){ return 0; } now=T[now].son[next]; } } void delet(int v){//删除权值为v的点 int now=find(v); if(!now)return; if(T[now].recy>1){ T[now].recy--; T[now].sum--; }else{ if(!T[now].son[0]&&!T[now].son[1]){ root=0; }else if(!T[now].son[0]){ root=T[now].son[1]; T[root].fa=0; }else{ int lef=T[now].son[0]; while(T[lef].son[1]){ lef=T[lef].son[1]; } splay(lef,T[now].son[0]); connect(T[now].son[1],lef,1); connect(lef,0,1); pushup(lef); } } } int _rank(int v){//查询权值为v的点的排名 return T[T[find(v)].son[0]].sum+1; } int _kth(int k){//查询第x名的权值 int now=root; while(1){ int used=T[now].sum-T[T[now].son[1]].sum; if(T[T[now].son[0]].sum<k&&k<=used){ splay(now,root); return T[now].v; } if(k<used){ now=T[now].son[0]; } else{ k-=used; now=T[now].son[1]; } } } int lower(int x){//前驱 int now=root,val=-0x3f3f3f3f; while(now){ if(T[now].v<x){ val=max(val,T[now].v); } if(T[now].v<x){ now=T[now].son[1]; }else { now=T[now].son[0]; } } return val; } int upper(int x){//后继 int now=root,val=0x3f3f3f3f; while(now){ if(T[now].v>x){ val=min(val,T[now].v); } if(T[now].v<=x){ now=T[now].son[1]; }else{ now=T[now].son[0]; } } return val; } int main () { n = read(); while (n--) { int opt = read(); int x = read(); if (opt == 1) Insert(x); else if (opt == 2) delet(x); else if (opt == 3) printf("%d\n", _rank(x)); else if (opt == 4) printf("%d\n", _kth(x)); else if (opt == 5) printf("%d\n", lower(x)); else if (opt == 6) printf("%d\n", upper(x)); } return 0; }
Treap
#include<bits/stdc++.h> using namespace std; const int N=300010; int n,cnt,root; struct node{ int v,recy,sum;//权值 重复个数 子树总个数 int son[2];// 儿子 int rk;//随机值 }T[N]; void pushup(int x){//更新大小 T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+T[x].recy; } void rotate(int &x,int next){//旋转 int y=T[x].son[next^1]; T[x].son[next^1]=T[y].son[next]; T[y].son[next]=x; pushup(x); pushup(y); x=y; } int newpoint(int v){//建新点 T[++cnt].v=v; T[cnt].sum=T[cnt].recy=1; T[cnt].rk=rand(); return cnt; } void Insert(int &x,int v){//插入权值为v的点 if(!x){x=newpoint(v);return;} if(T[x].v==v){ T[x].recy++; T[x].sum++; return; } int next=T[x].v<v?1:0; Insert(T[x].son[next],v); if(T[x].rk<T[T[x].son[next]].rk){ rotate(x,next^1); } pushup(x); } void delet(int &x,int v){//删除权值为v的点 if(!x)return; if(v<T[x].v){ delet(T[x].son[0],v); } else if(v>T[x].v){ delet(T[x].son[1],v); } else { if(!T[x].son[0]&&!T[x].son[1]){ T[x].recy--; T[x].sum--; if(!T[x].recy){ x=0; } }else if(T[x].son[0]&&T[x].son[1]){ int next=T[T[x].son[0]].rk>T[T[x].son[1]].rk?1:0; rotate(x,next); delet(T[x].son[next],v); }else{ int next=!T[x].son[1]; rotate(x,next); delet(T[x].son[next],v); } } pushup(x); } int _rank(int x,int v){//查询权值为v的点的排名 if(!x){ return 0; } else if(T[x].v<v){ return T[T[x].son[0]].sum+T[x].recy+_rank(T[x].son[1],v); }else if(T[x].v>v){ return _rank(T[x].son[0],v); }else{ return T[T[x].son[0]].sum+1; } } int _kth(int x,int k){//查询第k名的权值 if(!x){ return 0; }else if(T[T[x].son[0]].sum>=k){ return _kth(T[x].son[0],k); }else if(T[T[x].son[0]].sum+T[x].recy<k){ return _kth(T[x].son[1],k-T[T[x].son[0]].sum-T[x].recy); } else return T[x].v; } int lower(int x,int v){//前驱 if(!x){ return -0x3f3f3f3f; } if(T[x].v>=v){ return lower(T[x].son[0],v); }else{ return max(T[x].v,lower(T[x].son[1],v)); } } int upper(int x,int v){//后继 if(!x){ return 0x3f3f3f3f; } if(T[x].v<=v){ return upper(T[x].son[1],v); }else { return min(T[x].v,upper(T[x].son[0],v)); } } int main(){ scanf("%d",&n); for (int i=0;i<n;++i) { int opt,x; scanf("%d%d",&opt,&x); if (opt==1) Insert(root,x); else if (opt==2) delet(root,x); else if (opt==3) printf("%d\n",_rank(root,x)); else if (opt==4) printf("%d\n",_kth(root,x)); else if (opt==5) printf("%d\n",lower(root,x)); else if (opt==6) printf("%d\n",upper(root,x)); } return 0; }
fhq
#include<bits/stdc++.h> using namespace std; const int N=400010; int cnt,x,y,z,root; int n,m; struct node{ int v,sum;//权值 子树总个数 int son[2];//儿子 int rk;//随机值 }T[N]; 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*10+c-'0';c=getchar();} return x*f; } void pushup(int x){//更新大小 T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+1; } int newpoint(int v){//建新点 T[++cnt].v=v; T[cnt].sum=1; T[cnt].rk=rand(); return cnt; } int merge(int x,int y){//合并 if(!x||!y) return x+y; if(T[x].rk<T[y].rk){ T[x].son[1]=merge(T[x].son[1],y); pushup(x); return x; }else{ T[y].son[0]=merge(x,T[y].son[0]); pushup(y); return y; } } void split(int now,int k,int &x,int &y){//分裂(权值) if(!now) x=y=0; else { if(T[now].v<=k){ x=now; split(T[now].son[1],k,T[now].son[1],y); }else{ y=now; split(T[now].son[0],k,x,T[now].son[0]); } pushup(now); } } void _split(int now,int k,int &x,int &y){//分裂(排名) if(!now) x=y=0; else { if(T[T[now].son[0]].sum<k){ x=now; split(T[now].son[1],k-T[T[now].son[0]].sum-1,T[now].son[1],y); }else{ y=now; split(T[now].son[0],k,x,T[now].son[0]); } pushup(now); } } void Insert(int v){//输入 split(root,v,x,y); root=merge(merge(x,newpoint(v)),y); } void delet(int v){//删除 split(root,v,x,z); split(x,v-1,x,y); y=merge(T[y].son[0],T[y].son[1]); root=merge(merge(x,y),z); } int _rank(int v){//权值为v点的排名 split(root,v-1,x,y); int ans=T[x].sum+1; root=merge(x,y); return ans; } int find(int now,int k){//查询第k大点的编号 while(1){ if(k<=T[T[now].son[0]].sum){ now=T[now].son[0]; }else if(k==T[T[now].son[0]].sum+1){ return now; }else{ k-=T[T[now].son[0]].sum+1; now=T[now].son[1]; } } } int _kth(int k){//查询第k大点的权值 return T[find(root,k)].v; } int lower(int v){//前驱 split(root,v-1,x,y); int ans=T[find(x,T[x].sum)].v; root=merge(x,y); return ans; } int upper(int v){//后继 split(root,v,x,y); int ans=T[find(y,1)].v; root=merge(x,y); return ans; } int main(){ scanf("%d",&n); for (int i=0;i<n;++i){ int opt,x; scanf("%d%d",&opt,&x); if (opt==1) Insert(x); else if (opt==2) delet(x); else if (opt==3) printf("%d\n",_rank(x)); else if (opt==4) printf("%d\n",_kth(x)); else if (opt==5) printf("%d\n",lower(x)); else if (opt==6) printf("%d\n",upper(x)); } return 0; }
替罪羊(调了一天半呢....网上为什么都用的指针版的 自己写了个不用指针的)
#include<bits/stdc++.h> #define L(x) e[(x)].son[0] #define R(x) e[(x)].son[1] using namespace std; const int N=400010; struct node{ int son[2], val, imag, real; bool v; }e[N]; int avai[N]; int used[N]; int root, A, B, cnt, aim,bad,badfa; int newpoint(int v){ e[++cnt].val = v; e[cnt].v=1; e[cnt].imag=e[cnt].real = 1; e[cnt].son[0] = e[cnt].son[1] = 0; return cnt; } bool check(int x){ if((double)max(e[L(x)].imag,e[R(x)].imag)*1.0>(double)e[x].imag*0.8)return 0; else return 1; } void pushup(int x){ e[x].imag=e[L(x)].imag+e[R(x)].imag+1; e[x].real=e[L(x)].real+e[R(x)].real+e[x].v; } void pia(int x) { if(L(x))pia(L(x)); if(e[x].v)used[++A] = x; if(R(x))pia(R(x)); } int build(int l, int r){ if(l>r)return 0; int mid = (l+r)>>1; int x = used[mid]; L(x)=build(l,mid-1); R(x)=build(mid+1,r); pushup(x); return x; } void rebuild(){ if(!bad)return; int next=(R(badfa)==bad?1:0),last=bad; A=0;pia(bad);bad=build(1,A); e[badfa].son[next]=bad; if(last==root)root=bad; return; } int Ins(int x, int v,int fa){ if(!x){ x=newpoint(v); return x; } e[x].imag++; e[x].real++; if(e[x].val >= v) L(x)=Ins(L(x), v,x); else R(x)=Ins(R(x), v,x); if(!check(x)&&!bad){ bad=x; badfa=fa; } return x; } void Insert(int v){ bad=badfa=0; root=Ins(root,v,0); rebuild(); } int _rank(int k){ int x = root; int ans = 1; while(x){ if(e[x].val >= k) x = L(x); else{ ans += e[L(x)].real + e[x].v; x = R(x); } } return ans; } int _kth(int k){ int x = root; while(x){ if(e[x].v&&e[L(x)].real+1 == k) return e[x].val; else if(e[L(x)].real >= k) x = L(x); else{ k -= e[L(x)].real + e[x].v; x = R(x); } } return 0; } void delet_pos(int x, int v){ if(e[x].v&&e[L(x)].real+ 1 == v) { e[x].v = 0; e[x].real--; return; } e[x].real--; if(e[L(x)].real + e[x].v >= v) delet_pos(L(x), v); else delet_pos(R(x),v-e[L(x)].real-e[x].v); } void delet(int v){ delet_pos(root, _rank(v)); } int lower(int v){ return _kth(_rank(v)-1); } int upper(int v){ return _kth(_rank(v+1)); } int main() { int opt, x, m; scanf("%d",&m); while(m--) { scanf("%d%d",&opt,&x); if(opt == 1){Insert(x);} if(opt == 2){delet(x);} if(opt == 3){printf("%d\n",_rank(x));} if(opt == 4){printf("%d\n",_kth(x));} if(opt == 5){printf("%d\n",lower(x));} if(opt == 6){printf("%d\n",upper(x));} } return 0; }
可持久化平衡树:
fhq
#include<bits/stdc++.h> using namespace std; const int N=500010; int cnt,x,y,z,root[N],tot; int n,m; struct node{ int v,sum;//权值 子树总个数 int son[2];//儿子 int rk;//随机值 }T[N*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*10+c-'0';c=getchar();} return x*f; } void pushup(int x){//更新大小 if(x)T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+1; } int newpoint(int v){//建新点 T[++cnt].v=v; T[cnt].sum=1; T[cnt].rk=rand(); return cnt; } int copy(int x){ T[++cnt]=T[x]; return cnt; } void split(int now,int k,int &x,int &y){//分裂(权值) if(!now) x=y=0; else { // pushdown(now); if(T[now].v<=k){ x=copy(now); split(T[x].son[1],k,T[x].son[1],y); }else{ y=copy(now); split(T[y].son[0],k,x,T[y].son[0]); } pushup(x); pushup(y); } } void _split(int now,int k,int &x,int &y){//分裂(排名) if(!now) x=y=0; else { // pushdown(now); if(T[T[now].son[0]].sum<k){ x=copy(now); split(T[x].son[1],k-T[T[now].son[0]].sum-1,T[x].son[1],y); }else{ y=copy(now); split(T[y].son[0],k,x,T[y].son[0]); } pushup(x); pushup(y); } } int merge(int x,int y){//合并 if(!x||!y) return x+y; // pushdown(x); // pushdown(y); if(T[x].rk<T[y].rk){ int nu=copy(x); T[nu].son[1]=merge(T[nu].son[1],y); pushup(nu); return nu; }else{ int nu=copy(y); T[nu].son[0]=merge(x,T[nu].son[0]); pushup(nu); return nu; } } //另外 在需要推标记的题中如果pushdown会改变树的形态 注意开新点 /* 即在pushdown函数中加入以下代码 if(T[x].son[0])T[x].son[0]=copy(T[x].son[0]); if(T[x].son[1])T[x].son[1]=copy(T[x].son[1]); */ // 因为新的版本继承的旧版本的点嘛 pushdown的时候不能牵连到旧版本嘛 void Insert(int ed,int v){//输入 x=y=z=0; split(root[ed],v,x,y); root[ed]=merge(merge(x,newpoint(v)),y); } void delet(int ed,int v){//删除 x=y=z=0; split(root[ed],v,x,z); split(x,v-1,x,y); y=merge(T[y].son[0],T[y].son[1]); root[ed]=merge(merge(x,y),z); } int _rank(int ed,int v){//权值为v点的排名 x=y=z=0; split(root[ed],v-1,x,y); int ans=T[x].sum+1; root[ed]=merge(x,y); return ans; } int find(int now,int k){//查询第k大点的编号 while(1){ if(k<=T[T[now].son[0]].sum){ now=T[now].son[0]; }else if(k==T[T[now].son[0]].sum+1){ return now; }else{ k-=T[T[now].son[0]].sum+1; now=T[now].son[1]; } } } int _kth(int ed,int k){//查询第k大点的权值 x=y=z=0; return T[find(root[ed],k)].v; } int lower(int ed,int v){//前驱 x=y=z=0; split(root[ed],v-1,x,y); if(!x)return -2147483647; int ans=T[find(x,T[x].sum)].v; root[ed]=merge(x,y); return ans; } int upper(int ed,int v){//后继 x=y=z=0; split(root[ed],v,x,y); if(!y)return 2147483647; int ans=T[find(y,1)].v; root[ed]=merge(x,y); return ans; } int main(){ srand(time(NULL)); scanf("%d",&n); for (int i=1;i<=n;++i){//注意:由于模板题题意这里必须写成i=1 int opt,x,E; scanf("%d%d%d",&E,&opt,&x); root[i]=root[E]; if (opt==1) Insert(i,x); else if (opt==2) delet(i,x); else if (opt==3) printf("%d\n",_rank(i,x)); else if (opt==4) printf("%d\n",_kth(i,x)); else if (opt==5) printf("%d\n",lower(i,x)); else if (opt==6) printf("%d\n",upper(i,x)); } return 0; }
其他待补....