2018.07.06 BZOJ 1588: HNOI2002营业额统计(非旋treap)

时间:2022-05-16 15:47:59

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec Memory Limit: 162 MB

Description

营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。

 输入输出要求

Input

第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i

天公司的营业额。

天数n<=32767,

每天的营业额ai <= 1,000,000。

最后结果T<=2^31

Output

输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

Sample Input

6

5

1

2

5

4

6

Sample Output

12

HINT

结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

该题数据bug已修复.—-2016.5.15

一道与宠物收容所相似的简(s)单(b)题,仍然是用平衡树(set" role="presentation" style="position: relative;">setset)来维护前驱,后继,插入,然后就没了。本蒟蒻再次选择使用代码量相对较少的非旋treap" role="presentation" style="position: relative;">treaptreap来实现。

代码如下:

#include<bits/stdc++.h>
#define N 400005
using namespace std;
typedef pair<int,int> res;
int rt,son[N][2],siz[N],val[N],rd[N],cnt;
inline int build(int v){rd[++cnt]=rand(),val[cnt]=v,siz[cnt]=1,son[cnt][0]=son[cnt][1]=0;return cnt;}
inline void pushup(int p){siz[p]=siz[son[p][0]]+siz[son[p][1]]+1;}
inline int merge(int a,int b){
    if(!a||!b)return a+b;
    if(rd[a]<rd[b]){
        son[a][1]=merge(son[a][1],b);
        pushup(a);
        return a;
    }
    son[b][0]=merge(a,son[b][0]);
    pushup(b);
    return b;
}
inline res split(int p,int k){
    if(!p)return res(0,0);
    res ans,tmp;
    if(siz[son[p][0]]>=k){
        tmp=split(son[p][0],k);
        son[p][0]=tmp.second,pushup(p);
        ans.first=tmp.first;
        ans.second=p;
        return ans;
    }
    tmp=split(son[p][1],k-siz[son[p][0]]-1);
    son[p][1]=tmp.first,pushup(p);
    ans.first=p;
    ans.second=tmp.second;
    return ans;
}
inline int rank(int p,int v){
    if(!p)return 0;
    if(val[p]>v)return rank(son[p][0],v);
    return rank(son[p][1],v)+siz[son[p][0]]+1;
}
inline void ins(int v){
    int k=rank(rt,v);
    res x=split(rt,k);
    int p=build(v);
    rt=merge(merge(x.first,p),x.second);
}
inline void del(int v){
    int k=rank(rt,v);
    res x=split(rt,k);
    res y=split(x.first,k-1);
    rt=merge(y.first,x.second);
}
inline int pre(int p,int v){
    if(!p)return -0x3f3f3f3f;
    if(val[p]<=v)return max(val[p],pre(son[p][1],v));
    return pre(son[p][0],v);
}
inline int suf(int p,int v){
    if(!p)return 0x3f3f3f3f;
    if(val[p]>=v)return min(val[p],suf(son[p][0],v));
    return suf(son[p][1],v);
}
inline int read(){
    int ans=0,w=1;
    char ch=ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')w=-1;
        ch=getchar();
    }
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    return ans*w;
}
int main(){
    int n=read();
    int ans=0;
    while(n--){
        int x=read();
        if(!siz[rt])ans+=x;
        else{
            int a=pre(rt,x),b=suf(rt,x);
            ans+=min(abs(a-x),abs(b-x));
        }
        ins(x);
    }
    printf("%d",ans);
    return 0;
}