zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    洛谷P3400 仓鼠窝(单调栈)
    牛客练习赛65
    2015 HIAST Collegiate Programming Contest] 题解(AK)
    “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛)
    POJ 2421 Constructing Roads
    逆序数&&线段树
    HDU-1166 敌兵布阵 (线段树&&树状数组入门)
    Codeforces Round #484 (Div. 2)
    HDU
    HDU 5773 The All-purpose Zero (变形LIS)
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7689877.html
Copyright © 2011-2022 走看看