bzoj 1588: [HNOI2002]营业额统计 spaly

来源:互联网 发布:mysql注入式攻击 编辑:程序博客网 时间:2024/05/22 09:01

题目链接:bzoj1588

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 17048  Solved: 6880
[Submit][Status][Discuss]

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

Source

[Submit][Status][Discuss]
题目分析:splay模板,每次输入一个数,如果这个数以前出现过那么就不要插入,同时当天最小波动值为0,否则插入然后比较其与前驱和后继的差值,取小的加上,注意判断下没有前驱或后继的情况。

////  main.cpp//  bzoj1588////  Created by teddywang on 2017/09/05.//  Copyright © 2017年 teddywang. All rights reserved.#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;#define inf 1e9const int maxn=1e6+10;ll ch[maxn][2];//ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子ll fa[maxn];//f[i]表示i的父结点ll size[maxn];//size[i]表示包括i的这个子树的大小ll cnt[maxn];//cnt[i]表示i结点的关键字出现的次数(相当于权值)ll key[maxn];//key[i]表示i的关键字(即结点i代表的那个数字)ll sz,root;//sz为整棵树的大小,root为整棵树的根void clear(ll x)//将当前点的各项值都清0 用于删除之后{    ch[x][0]=ch[x][1]=fa[x]=size[x]=cnt[x]=key[x]=0;}bool get(ll x)//判断当前点是它父结点的左儿子还是右儿子{    return ch[fa[x]][1]==x;}void update(ll x)//更新当前点的size值(用于发生修改之后){    if(x)    {        size[x]=cnt[x];        if(ch[x][0]) size[x]+=size[ch[x][0]];        if(ch[x][1]) size[x]+=size[ch[x][1]];    }}void rotate(ll x)//旋转x节点{    ll old=fa[x],oldf=fa[old],whichx=get(x);    ch[old][whichx]=ch[x][whichx^1];    fa[ch[old][whichx]]=old;    ch[x][whichx^1]=old;    fa[old]=x;    fa[x]=oldf;    if(oldf) ch[oldf][ch[oldf][1]==old]=x;    update(old);    update(x);}void splay(ll x)//直接rotate到根{    for(ll f;(f=fa[x]);rotate(x))    {        if (fa[f]) rotate(get(x)==get(f)?f:x);    }    root=x;}inline bool insert(ll x){    if (root==0){sz++; ch[sz][0]=ch[sz][1]=fa[sz]=0; root=sz; size[sz]=cnt[sz]=1; key[sz]=x; return 1;}    ll now=root,f=0;    while(1){        if (x==key[now]){            cnt[now]++; update(now); update(f); splay(now);            return 0;        }        f=now;        now=ch[now][key[now]<x];        if (now==0){            sz++;            ch[sz][0]=ch[sz][1]=0;            fa[sz]=f;            size[sz]=cnt[sz]=1;            ch[f][key[f]<x]=sz;            key[sz]=x;            update(f);            splay(sz);            return 1;        }    }    return 0;}inline ll pre(){    ll now=ch[root][0];    if(now==0) return inf;    while (ch[now][1]) now=ch[now][1];    return now;}inline ll next(){    ll now=ch[root][1];    if(now==0) return inf;    while (ch[now][0]) now=ch[now][0];    return now;}int main(){    ll n;    while(~scanf("%lld",&n))    {        memset(ch,0,sizeof(ch));        memset(key,0,sizeof(key));        ll ans=0;        for(int i=0;i<n;i++)        {            ll x;            scanf("%lld",&x);            if(i==0)            {                insert(x);                ans+=abs(x);                continue;            }            if(insert(x)==0) continue;            ll buf1,buf2;            if(pre()==inf) buf1=inf;            else buf1=x-key[pre()];            if(next()==inf) buf2=inf;            else buf2=key[next()]-x;            ans+=abs(min(buf1,buf2));//            cout<<buf1<<" "<<x<<" "<<buf2<<" "<<ans<<endl;        }        printf("%lld\n",ans);    }}