HYSBZ - 1588 splay

Posted walfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HYSBZ - 1588 splay相关的知识,希望对你有一定的参考价值。

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

题解: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\n",ans);
    }
    return 0;
}
/********************

********************/
View Code

 

以上是关于HYSBZ - 1588 splay的主要内容,如果未能解决你的问题,请参考以下文章

HYSBZ_1588_set

营业额统计 HYSBZ - 1588

HYSBZ - 1500 (splay)

bzoj 1588 splay模板题

bzoj1588: [HNOI2002]营业额统计 splay瞎写

BZOJ-1588营业额统计 Splay