zoukankan      html  css  js  c++  java
  • Splay板子

    本代码由张大仙独家冠名
    从张大仙那里翻译而来。原链接大仙的Splay超详细讲解!学Splay这一篇就够了!
    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=100000+10,Inf=0x3f3f3f3f;
    int ch[maxn][2],cnt[maxn],size[maxn],val[maxn],fa[maxn];
    int root,tot,n,m;
    void update(int x){
        size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
    }
    void rotate(int x){
        int y=fa[x],z=fa[y],k=(ch[y][1]==x) ;
        ch[z][ch[z][1]==y] = x;
        fa[x]=z;
        ch[y][k]=ch[x][!k];
        fa[ch[x][!k]]=y;
        ch[x][!k]=y;
        fa[y]=x;
        update(y);
        update(x);
    }
    void Splay(int x,int t){
        while(fa[x]!=t){
            int y=fa[x],z=fa[y];
            if(z!=t) (ch[y][0]==x)^(ch[z][0]==y) ? rotate(y) : rotate(x) ;
            rotate(x);
        }
        if(!t) root=x;
    }
    void find(int x){
        int u=root;
        while(ch[u][x>val[u]]&&x!=val[u]) u=ch[u][x>val[u]];
        Splay(u,0);
    }
    void Insert(int x){
        int u=root,f=0;
        while(u && x!=val[u]){
            f=u;
            u=ch[u][x>val[u]];
        }
        if(u) cnt[u]++;
        else{
            u=++tot;
            if(f) ch[f][x>val[f]] = u;
            val[u]=x;
            fa[u]=f;
            cnt[u]=size[u]=1;
        }
        Splay(u,0);
    }
    int pre(int x){
        find(x);
        if(x>val[root]) return root;
        int u=ch[root][0];
        if(!u) return -1;
        while(ch[u][1]) u=ch[u][1];
        return u;
    }
    int next(int x){
        find(x);
        if(x<val[root]) return root;
        int u=ch[root][1];
        if(!u) return -1;
        while(ch[u][0]) u=ch[u][0];
        return u;
    }
    void Delete(int x){
        int xp=pre(x),xn=next(x);
        Splay(xp,0);
        Splay(xn,root);
        int u=ch[xn][0];
        if(cnt[u]>1){
            cnt[u]--;
            Splay(u,0);
        }
        else{
            ch[xn][0]=0;
            update(xp);
            update(xn);
        }
    }
    int kth(int x){
        int u=root;
        if(size[u]<x) return -1;
        while(1){
            if(x<=size[ch[u][0]]) u=ch[u][0];
            else if(x>size[ch[u][0]]+cnt[u]){
                x-=size[ch[u][0]]+cnt[u];
                u=ch[u][1];
            }
            else return u;
        }
    }
    int rank(int x){
        find(x);
        return size[ch[root][0]];
    }
    void Solve(){
        scanf("%d",&n);
        Insert(-Inf);Insert(Inf);
        for(int i=1,op,x;i<=n;++i){
            scanf("%d%d",&op,&x);
            if(op==1) Insert(x);
            else if(op==2) Delete(x);
            else if(op==3) printf("%d
    ",rank(x)); 
            else if(op==4) printf("%d
    ",val[kth(x+1)]);
            else if(op==5) printf("%d
    ",val[pre(x)]);
            else printf("%d
    ",val[next(x)]);
        }
    }
    int main(){
        Solve();
        return 0;
    }
    
  • 相关阅读:
    19面向对象--特殊成员
    18面向对象--成员和组合
    17面向对象--三大特性
    16异常处理
    15(os、random、sys、)(json、pickle )
    14python模块之re
    13正则表达式
    12内置函数补充,递归以及二分法。
    Linux环境ftp搭建及问题总结
    运维之路—linux忘记密码修改(rd.breake 方式)
  • 原文地址:https://www.cnblogs.com/wwcdcpyscc/p/13496281.html
Copyright © 2011-2022 走看看