zoukankan      html  css  js  c++  java
  • BZOJ 1588:splay tree

    刚学习的splay tree。照着大神的代码敲了敲,理解了个大概

    很好用的数据结构,可以用来维护数列

    学习时建议先看看SBT,这样可以更好地理解“旋转”

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"vector"
    #define ll long long
    #define mems(a,b) memset(a,b,sizeof(a))
    
    using namespace std;
    const int MAXN = 1e5+50;
    const int MAXE = 200500;
    const int INF = 0x3f3f3f;
    
    int pre[MAXN],val[MAXN],ch[MAXN][2];///父亲结点、值、孩子节点(0左1右)
    int tot,root;///总结点数、根节点
    ///中序遍历为所维护数列
    
    void newnode(int &pos,int fa,int w){
        pos=++tot;
        pre[pos]=fa;
        val[pos]=w;
        ch[pos][0]=ch[pos][1]=0;
    }
    
    void Rotate(int x,int kind){///0左1右
        int fa=pre[x];
        ch[fa][!kind]=ch[x][kind];
        pre[ch[x][kind]]=fa;
    
        if(pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa]=x;
        pre[x]=pre[fa];
    
        ch[x][kind]=fa;
        pre[fa]=x;
    }
    
    void Splay(int r,int goal){///将r结点旋转至goal下方
        while(pre[r]!=goal){
            if(pre[pre[r]]==goal) Rotate(r,ch[pre[r]][0]==r);
            else{
                int fa=pre[r];
                int kind=ch[pre[fa]][0]==fa;
                if(ch[fa][kind]==r){///左右交替
                    Rotate(r,!kind);
                    Rotate(r,kind);
                }
                else{               ///方向一致
                    Rotate(fa,kind);
                    Rotate(r,kind);
                }
            }
        }
        if(!goal) root=r;///goal为不存在结点时,r为变为根节点
    }
    
    bool Insert(int key){
        int r=root;
        while(ch[r][val[r]<key]){
            if(val[r]==key){///相同值只插入一次
                Splay(r,0);
                return false;
            }
            r=ch[r][val[r]<key];
        }
        newnode(ch[r][val[r]<key],r,key);
        Splay(ch[r][val[r]<key],0);
        return true;
    }
    ///BST查询复杂度log(n)
    int get_pre(int x){///寻找比X大但最接近X的数
        int t=ch[x][0];
        if(!t) return INF;
        while(ch[t][1]) t=ch[t][1];
        return val[x]-val[t];
    }
    
    int get_next(int x){///寻找比X小但最接近X的数
        int t=ch[x][1];
        if(!t) return INF;
        while(ch[t][0]) t=ch[t][0];
        return val[t]-val[x];
    }
    
    int main(){
        int n;
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            root=tot=0;
            int ans=0;
            for(int i=1;i<=n;i++){
                int x;
                if(scanf("%d",&x)==EOF) x=0;
                if(i==1){
                    ans+=x;
                    newnode(root,0,x);
                    continue;
                }
                if(!Insert(x)) continue;
    
                ans+=min(get_pre(root),get_next(root));
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    新巴巴运动网 项目第二天
    新巴巴运动网 项目第一天
    pandas.read_csv()参数(转载)
    from sklearn.datasets import make_classification创建分类数据集
    【剑指offer】08二叉树的下一个节点,C++实现
    【剑指offer】滑动窗口的最大值,C++实现
    【剑指offer】找出数组中任意重复的数字(不修改数组),C++实现
    步入element-ui踩坑记
    步入vue.js踩坑记
    nvm安装与使用
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5127203.html
Copyright © 2011-2022 走看看