P3369 【模板】普通平衡树(splay)

时间:2022-11-29 18:23:26

P3369 【模板】普通平衡树

就是不用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[],fa,siz;}a[];
#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+;}
void turn(int x,int &k){
int y=a[x].fa,z=a[y].fa;
int l=(a[y].ch[]==x),r=l^;
if(y==k) k=x;
else a[z].ch[a[z].ch[]==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[]==x)^(a[z].ch[]==y))?x:y,k);
}
}
int find(int o,int k){//查找排名为k的点的位置
while(k!=a[lc].siz+){
if(a[lc].siz+>=k) o=lc;
else k=k-a[lc].siz-,o=rc;
}return o;
}
int torank(int o,int k){//排名查询
int re=,id=;
while(o){
if(a[o].v==k) id=o;
if(a[o].v>=k) o=lc;
else re+=a[lc].siz+,o=rc;
}
if(id) splay(id,rt);//保证复杂度
return re;
}
void ins(int k){//添加
int o=rt,Fa=;
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[]=rc; a[rc].fa=lc;
rt=lc; up(rt); a[rt].fa=;
}else if(lc) a[lc].fa=,rt=lc;
else if(rc) a[rc].fa=,rt=rc;
else rt=;
}
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==) ins(q2);
else if(q1==) del(q2);
else if(q1==) printf("%d\n",torank(rt,q2)+);//记得排名+1
else if(q1==) printf("%d\n",a[find(rt,q2)].v);
else if(q1==) ans=-1e9,pre(rt,q2),printf("%d\n",ans);
else ans=1e9,last(rt,q2),printf("%d\n",ans);
}return ;
}