【HYSBZ1588: [HNOI2002]】营业额统计——伸展树

来源:互联网 发布:海盗船水冷控制软件 编辑:程序博客网 时间:2024/05/17 09:08

Time Limit: 5 Sec Memory Limit: 162 MB

Description

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

Input

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

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

伸展树初步,在看完网上对伸展树的基本操作后,试着敲了敲,发现了自己的Zig和Zag敲错了,好惨。用链表的,感觉写的很挫,慢慢的变得精炼的。
思路:每一次将插入的数提到根节点,那么对于一二叉查找树来说,根节点的前驱就是左子树的最右边的节点,后继就是右子树最左边的节点。那么就可以得到最小的波动值。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <string>#include <queue>#include <stack>#include <set>#include <map>#include <vector>#include <algorithm>using namespace std;typedef long long LL;const int INF = 0x3f3f3f3f;typedef struct node{    int data;    node *Lch,*Rch,*fa;}Tree;Tree * Creat(int data){    Tree *p ;    p = new node;    p->data = data;    p->Lch = p->Rch = p->fa = NULL;    return p;}Tree * Insert(int data,Tree * u){//插入节点    if(u->data == data)        return NULL;    if(u->data>data){        if(u->Lch == NULL){            u->Lch = Creat(data);            u->Lch ->fa = u;            return u->Lch;        }        else            return Insert(data,u->Lch);    }    else{        if(u->Rch == NULL){            u->Rch = Creat(data);            u->Rch->fa = u;            return u->Rch;        }        else            return Insert(data,u->Rch);    }    return NULL;}void Zig(Tree *u){//右旋    Tree *fa,*p,*Gfa;    bool flag = false;    fa = u->fa;    Gfa = fa->fa;    if(Gfa&&Gfa->Rch == fa)        flag = true;    p = u->Rch;    u->fa = Gfa;    u->Rch = fa;    fa->fa = u;    fa->Lch = p;    if(p)        p->fa = fa;    if(Gfa){        if(flag)            Gfa->Rch = u;        else Gfa->Lch = u;    }}void Zag(Tree * u){//左旋    Tree *fa ,*p,*Gfa;    bool flag = false;    fa = u->fa ;    Gfa= fa->fa;    if(Gfa&&Gfa->Rch == fa)        flag = true;    p = u->Lch;    u->fa = fa->fa;    u->Lch = fa;    fa->fa = u;    fa->Rch = p;    if(p)        p->fa = fa;    if(Gfa){        if(flag)            Gfa->Rch = u;        else Gfa->Lch = u;    }}Tree * Rotate(Tree *u){//将节点提到根处。    Tree *fa , *Gfa;    while(u->fa != NULL){        fa = u->fa;        Gfa = fa->fa;        if(Gfa == NULL){            if(fa->Lch == u)                Zig(u);            else                Zag(u);        }        else{            if(Gfa->Lch == fa){                if(fa->Lch == u)                    Zig(u);                else                    Zag(u);                Zig(u);            }            else{                if(fa->Lch == u)                    Zig(u);                else                    Zag(u);                Zag(u);            }        }    }    return u;}int Find_Pre(Tree *u,int data){//找节点的前驱    if(u == NULL) return INF;    if(u->Rch == NULL) return data-u->data;    else return Find_Pre(u->Rch,data);}int Find_Next(Tree *u,int data){//找节点的后继    if(u == NULL) return INF;    if(u->Lch == NULL) return u->data-data;    else return Find_Next(u->Lch,data);}int main(){    int n;    while(~scanf("%d",&n)){        Tree *root,*p;        int ans = 0,data;        for(int i = 0;i < n; i++){            scanf("%d",&data);            if(!i){                ans += abs(data);                root = Creat(data);            }            else{                 p = Insert(data,root);                 if(p == NULL) continue;                 root = Rotate(p);                 int a = Find_Pre(root->Lch,data);                 int b = Find_Next(root->Rch,data);                 ans+=min(a,b);            }        }        printf("%d\n",ans);    }    return 0;}
0 0