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

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[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;
}

 

posted @ 2019-03-24 21:23  kafuuchino  阅读(212)  评论(0编辑  收藏  举报