安利splay讲解:
【模板】普通平衡树(luogu)
Description
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 xx 数
- 删除 xx 数(若有多个相同的数,因只删除一个)
- 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
- 查询排名为 xx 的数
- 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
- 求 xx 的后继(后继定义为大于 xx,且最小的数)
输入格式
第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 \text{opt}opt 和 xx,\text{opt}opt 表示操作的序号( 1 \leq \text{opt} \leq 61≤opt≤6 )
输出格式
对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案
Code
#include <iostream> using namespace std; const int N=1e5+10; //1:插入xx数 //2:删除xx数(若有多个相同的数,因只删除一个) //3:查询xx数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名) //4:查询排名为xx的数 //5:求xx的前驱(前驱定义为小于xx,且最大的数) //6:求xx的后继(后继定义为大于xx,且最小的数) int n,x,opt,cnt[N],size[N],val[N],tot,ch[N][2],rt,fa[N]; struct Splay { void push_up(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x]; } bool get(int x) { return x==ch[fa[x]][1]; } void clear(int x) { size[x]=ch[x][0]=ch[x][1]=cnt[x]=val[x]=fa[x]=0; } void rotate(int x) { int y=fa[x],z=fa[y],wh=get(x); fa[ch[x][wh^1]]=y; ch[y][wh]=ch[x][wh^1]; ch[x][wh^1]=y; fa[x]=z,fa[y]=x; if(z) ch[z][y==ch[z][1]]=x; push_up(y),push_up(x); } void splay(int x) { for(int f=fa[x];f=fa[x],f;rotate(x)) if(fa[f]) rotate(get(f)==get(x)?f:x); rt=x; } int nxt() { int now=ch[rt][1]; while(ch[now][0]) now=ch[now][0]; return now; } int pre() { int now=ch[rt][0]; while(ch[now][1]) now=ch[now][1]; return now; } int rk(int x) { int res=0,now=rt; while(1) { if(x<val[now]) now=ch[now][0]; else { res+=size[ch[now][0]]; if(x==val[now]) { splay(now); return res+1; } res+=cnt[now],now=ch[now][1]; } } } int kth(int x) { int now=rt; while(1) { if(ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0]; else { x-=size[ch[now][0]]+cnt[now]; if(x<=0) return val[now]; now=ch[now][1]; } } } void ins(int x) { if(!rt) { rt=++tot,cnt[tot]=1,val[tot]=x; push_up(tot); return ; } int now=rt,par=0; while(1) { if(val[now]==x) { cnt[now]++; push_up(now),push_up(par); splay(now); return ; } par=now,now=ch[now][x>val[now]]; if(!now) { cnt[++tot]=1,val[tot]=x,fa[tot]=par; ch[par][x>val[par]]=tot; push_up(tot),push_up(par); splay(tot); return ; } } } void del(int x) { rk(x); if(cnt[rt]>1) cnt[rt]--,push_up(rt); else if(!ch[rt][0] && !ch[rt][1]) clear(rt),rt=0; else if(!ch[rt][0]) { int now=rt; rt=ch[rt][1],fa[rt]=0; clear(now); } else if(!ch[rt][1]) { int now=rt; rt=ch[rt][0],fa[rt]=0; clear(now); } else { int x=pre(),now=rt; splay(x); fa[ch[now][1]]=rt; ch[rt][1]=ch[now][1]; clear(now); push_up(rt); } } }tree; int main() { ios::sync_with_stdio(false); cin>>n; while(n--) { cin>>opt>>x; if(opt==1) tree.ins(x); else if(opt==2) tree.del(x); else if(opt==3) cout<<tree.rk(x)<<endl; else if(opt==4) cout<<tree.kth(x)<<endl; else if(opt==5) tree.ins(x),cout<<val[tree.pre()]<<endl,tree.del(x); else if(opt==6) tree.ins(x),cout<<val[tree.nxt()]<<endl,tree.del(x); } return 0; }
来源:https://www.cnblogs.com/hsez-cyx/p/12244736.html