• 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
    ",torank(rt,q2)+1);//记得排名+1
            else if(q1==4) printf("%d
    ",a[find(rt,q2)].v);
            else if(q1==5) ans=-1e9,pre(rt,q2),printf("%d
    ",ans);
            else ans=1e9,last(rt,q2),printf("%d
    ",ans);
        }return 0;
    }
  • 相关阅读:
    C# WinForm dataGridView 技巧小结
    Win7设置局域网共享
    vs2010快捷键大全
    C# WebBrowser.DocumentCompleted 多次调用解决方法
    为应用程序池 'DefaultAppPool' 提供服务的进程关闭时间超过了限制
    VB高清图标制作方法
    sqlite 中文排序
    一个vbs文件将指定文件夹下的文件名输出到指定文件夹下
    用DOS命令获取文件列表
    文件搜索神器 Everything
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10590495.html
Copyright © 2020-2023  润新知