HNOI2002——营业额统计(SBT)

来源:互联网 发布:工程三维绘图软件 编辑:程序博客网 时间:2024/04/30 10:23
营业额统计
(turnover.exe)

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
该天的最小波动值 
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额。
输入输出要求
输入由文件’turnover.in’读入。
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数 ,表示第i天公司的营业额。
输出到文件’turnover.out’。
输出文件仅有一个正整数,即 。结果小于 。
输入输出样例
Turnover.in Turnover.out
6
5
1
2
5
4
6 12

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

解析:

        很裸的SBT,直接每次插入的时候找前驱和后继,比较一下就累加。。。

         但是要要check一下前驱或后继是否为空。。。

         注意这道题数据有坑,就不提了。。。

代码:

/**************************************************************    Problem: 1588    User: jianing    Language: C++    Result: Accepted    Time:208 ms    Memory:1588 kb****************************************************************/ #include<cstdio>#include<algorithm>using namespace std;int n,tot;struct SBT{    int key,size,left,right;    void init()    {        left=right=0;        size=1;    }}tree[50000]; void left(int &p){    int k=tree[p].right;    tree[p].right=tree[k].left;    tree[k].left=p;    tree[k].size=tree[p].size;    tree[p].size=tree[tree[p].left].size+tree[tree[p].right].size+1;    p=k;} void right(int &p){    int k=tree[p].left;    tree[p].left=tree[k].right;    tree[k].right=p;    tree[k].size=tree[p].size;    tree[p].size=tree[tree[p].left].size+tree[tree[p].right].size+1;    p=k;} void maintain(int &p,int flag){    if(flag)    {        if(tree[tree[tree[p].right].right].size>tree[tree[p].left].size)left(p);        else if(tree[tree[tree[p].right].left].size>tree[tree[p].left].size)        {            right(tree[p].right);            left(p);        }else return ;    }else    {        if(tree[tree[tree[p].left].left].size>tree[tree[p].right].size)right(p);        else if(tree[tree[tree[p].left].right].size>tree[tree[p].right].size)        {            left(tree[p].left);            right(p);        }else return ;    }    maintain(tree[p].left,0);    maintain(tree[p].right,1);    maintain(p,0);    maintain(p,1);} void insert(int &p,int k){    if(p==0)    {        p=++tot;        tree[p].init();        tree[p].key=k;    }    else    {        tree[p].size++;        if(k<tree[p].key)insert(tree[p].left,k);        else insert(tree[p].right,k);        maintain(p,tree[p].key<=k);    }} int get_pre(int &p,int k){    if(!p)return k;    if(k<=tree[p].key)return get_pre(tree[p].left,k);    else    {        int t=get_pre(tree[p].right,k);        return t==k?tree[p].key:t;    }} int get_next(int &p,int k){    if(!p)return k;    if(k>=tree[p].key)return get_next(tree[p].right,k);    else    {        int t=get_next(tree[p].left,k);        return t==k?tree[p].key:t;    }} int check(int &p,int x){    if(p==0)return 0;    if(x<tree[p].key)return check(tree[p].left,x);    else if(x==tree[p].key)return 1;    else return check(tree[p].right,x);} void read(){    //freopen("HNOI.in","r",stdin);    //freopen("HNOI.out","w",stdout);    scanf("%d",&n);    int root=0,ans=0,kiss;    scanf("%d",&kiss);    insert(root,kiss);    ans+=kiss;    for(int i=2;i<=n;i++)    {        if(scanf("%d",&kiss)==EOF)kiss=0;        if(check(root,kiss))continue;        int s1=get_pre(root,kiss);        int s2=get_next(root,kiss);        if(s1==kiss)ans+=s2-kiss;else if(s2==kiss)ans+=kiss-s1;        if(kiss-s1<s2-kiss)ans+=kiss-s1; else ans+=s2-kiss;        insert(root,kiss);    }    printf("%d\n",ans);} int main(){    read();    return 0;}