码迷,mamicode.com
首页 > 其他好文 > 详细

HYSBZ - 1588 splay

时间:2017-10-19 00:17:54      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:air   using   查找   display   abs   view   value   show   fat   

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

题解: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

标签:air   using   查找   display   abs   view   value   show   fat   

原文地址:http://www.cnblogs.com/acjiumeng/p/7689877.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!