P3369 【模板】普通平衡树(splay)
就是不用treap
splay板子,好好背吧TAT
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define N 100005 int n,cnt,rt,ans,q1,q2; struct data{int v,ch[2],fa,siz;}a[100005]; #define lc a[o].ch[0] #define rc a[o].ch[1] void up(int o){a[o].siz=a[lc].siz+a[rc].siz+1;} void turn(int x,int &k){ int y=a[x].fa,z=a[y].fa; int l=(a[y].ch[1]==x),r=l^1; if(y==k) k=x; else a[z].ch[a[z].ch[1]==y]=x; a[a[x].ch[r]].fa=y; a[x].fa=z; a[y].fa=x; a[y].ch[l]=a[x].ch[r]; a[x].ch[r]=y; up(y); up(x); } void splay(int x,int &k){ for(;x!=k;turn(x,k)){ int y=a[x].fa,z=a[y].fa; if(y!=k) turn(((a[y].ch[0]==x)^(a[z].ch[0]==y))?x:y,k); } } int find(int o,int k){//查找排名为k的点的位置 while(k!=a[lc].siz+1){ if(a[lc].siz+1>=k) o=lc; else k=k-a[lc].siz-1,o=rc; }return o; } int torank(int o,int k){//排名查询 int re=0,id=0; while(o){ if(a[o].v==k) id=o; if(a[o].v>=k) o=lc; else re+=a[lc].siz+1,o=rc; } if(id) splay(id,rt);//保证复杂度 return re; } void ins(int k){//添加 int o=rt,Fa=0; while(o) Fa=o,o=a[o].ch[a[o].v<=k]; o=++cnt; a[o].v=k; a[o].fa=Fa; if(rt) a[Fa].ch[a[Fa].v<=k]=o,splay(o,rt);//保证复杂度 else rt=o; } void del(int k){//删除 int o=rt,tmp; while(a[o].v!=k) o=a[o].ch[a[o].v<=k]; splay(o,rt); if(lc&&rc){//分类讨论 tmp=find(rt,a[lc].siz); splay(tmp,lc); o=rt; a[lc].ch[1]=rc; a[rc].fa=lc; rt=lc; up(rt); a[rt].fa=0; }else if(lc) a[lc].fa=0,rt=lc; else if(rc) a[rc].fa=0,rt=rc; else rt=0; } void pre(int o,int k){//前驱 if(!o) return; if(ans<a[o].v&&a[o].v<k) ans=a[o].v; pre(a[o].ch[a[o].v<k],k); } void last(int o,int k){//后缀 if(!o) return; if(k<a[o].v&&a[o].v<ans) ans=a[o].v; last(a[o].ch[a[o].v<=k],k); } int main(){ scanf("%d",&n); while(n--){ scanf("%d%d",&q1,&q2); if(q1==1) ins(q2); else if(q1==2) del(q2); else if(q1==3) printf("%d\n",torank(rt,q2)+1);//记得排名+1 else if(q1==4) printf("%d\n",a[find(rt,q2)].v); else if(q1==5) ans=-1e9,pre(rt,q2),printf("%d\n",ans); else ans=1e9,last(rt,q2),printf("%d\n",ans); }return 0; }