• HYSBZ


    题意:每天给你一个数,要求统计最小波动值,强制在线的就是每次从已经出现过的数值中找与当前值间隔最小的加起来

    题解:splay维护,同时求解当前值的前驱和后继,找距离小的那个就好了

    splay是一种二叉搜索树,可以在log(n)的时间内维护,而且通过左旋和右旋避免二叉搜索树退化成一条链,而且可以利用二叉搜索树性质方便的查找前驱和后继

    推荐博客

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define C 0.5772156649
    #define pi acos(-1.0)
    #define ll long long
    #define mod 20090717
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    
    using namespace std;
    
    const double g=10.0,eps=1e-7;
    const int N=50000+10,maxn=60000+10,inf=0x3f3f3f;
    
    int rightson[N],leftson[N],father[N],value[N];
    ll ans;
    bool f;
    int tot,n,root;
    void right_rotate(int x)
    {
        int y=father[x],z=father[y];
        leftson[y]=rightson[x];
        if(rightson[x]!=-1)father[rightson[x]]=y;
        father[x]=z;
        if(z!=-1)
        {
            if(leftson[z]==y)leftson[z]=x;
            else rightson[z]=x;
        }
        father[y]=x;rightson[x]=y;
    }
    void left_rotate(int x)
    {
        int y=father[x],z=father[y];
        rightson[y]=leftson[x];
        if(leftson[x]!=-1)father[leftson[x]]=y;
        father[x]=z;
        if(z!=-1)
        {
            if(leftson[z]==y)leftson[z]=x;
            else rightson[z]=x;
        }
        father[y]=x;leftson[x]=y;
    }
    void splay(int x)//一直旋转到x成为root
    {
      //  cout<<x<<"-----------"<<endl;
        while(father[x]!=-1)
        {
         //   cout<<x<<" "<<father[x]<<endl;
            int y=father[x],z=father[y];
            if(z==-1)
            {
                if(rightson[y]==x)left_rotate(x);
                else right_rotate(x);
            }
            else
            {
                if(rightson[z]==y&&rightson[y]==x)left_rotate(y),left_rotate(x);
                else if(rightson[z]==y&&leftson[y]==x)right_rotate(x),left_rotate(x);
                else if(leftson[z]==y&&rightson[y]==x)left_rotate(x),right_rotate(x);
                else right_rotate(y),right_rotate(x);
            }
        }
        root=x;
    }
    void BSTinsert(int v,int x)//在二叉搜索树里插入
    {
       // cout<<x<<"-------"<<value[x]<<"---------"<<v<<endl;
        if(value[x]==v)//已经存在了
        {
            splay(x);
            f=0;
            return ;
        }
        if(value[x]>v)
        {
            if(leftson[x]==-1)//插在此处
            {
                leftson[x]=tot;
                father[tot]=x;
                leftson[tot]=rightson[tot]=-1;
                value[tot]=v;
            }
            else BSTinsert(v,leftson[x]);
        }
        else
        {
            if(rightson[x]==-1)
            {
                rightson[x]=tot;
                father[tot]=x;
                leftson[tot]=rightson[tot]=-1;
                value[tot]=v;
            }
            else BSTinsert(v,rightson[x]);
        }
    }
    int qq(int x)//前驱
    {
        int y=leftson[x];
        if(y==-1)return y;
        while(rightson[y]!=-1)y=rightson[y];
        return y;
    }
    int hj(int x)//后继
    {
        int y=rightson[x];
        if(y==-1)return y;
        while(leftson[y]!=-1)y=leftson[y];
        return y;
    }
    void insertpoint(int v)
    {
        tot++;
        f=1;
        BSTinsert(v,root);
        if(!f)
        {
            tot--;
            return ;//有重复的点
        }
       // cout<<value[tot]<<"*****************"<<father[tot]<<endl;
        splay(tot);
        int q=qq(tot),h=hj(tot);//找前驱和后继
        int res=3000000;
        if(q!=-1)res=min(res,abs(value[tot]-value[q]));
        if(h!=-1)res=min(res,abs(value[tot]-value[h]));
        ans+=res;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            scanf("%lld",&ans);
            tot=1;father[tot]=-1;
            leftson[tot]=rightson[tot]=-1;
            value[tot]=ans,root=tot;
            for(int i=2;i<=n;i++)
            {
                int a;
                scanf("%d",&a);
                insertpoint(a);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    /********************
    
    ********************/
    View Code
  • 相关阅读:
    Axure 实现数字自动加键功能(点击“+”数字加1,点击“-”数字减1)
    Axure 实现批量的勾选和反选
    传说中的AutoCAD公司
    Autodesk 最新开发技术研讨会-北京-上海-武汉-成都-西安-PPT下载
    发布App,赢iPad mini + 美金100$
    无插件的大模型浏览器Autodesk Viewer开发培训-武汉-2014年8月28日 9:00 – 12:00
    为Autodesk Viewer添加自定义工具条的更好方法
    为Autodesk Viewer添加自定义工具条
    Autodesk 最新开发技术研讨会 -8月22日-Autodesk北京办公室
    请保护我们的地球
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7689877.html
Copyright © 2020-2023  润新知