1588: [HNOI2002]营业额统计

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

提议清晰;

明显是考树结构,然后果断set水过--------罪过啊

其实splay就可以搞定,基于bst,插入一个节点就旋转为根节点,然后根据splay的性质,根节点一定小于所有右子树的节点,一定大于所有左子树的节点

那么距离根节点最近的点一定是左子树的最大值,或者右子树的最小值啊

/**************************************************************
    Problem: 1588
    User: 16112403012
    Language: C++
    Result: Accepted
    Time:172 ms
    Memory:3632 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100010
struct Node
{
    int key, sz, cnt;
    Node *ch[2], *pnt;//左右儿子和父亲
    Node() {}
    Node(int x, int y, int z)
    {
        key = x, sz = y, cnt = z;
    }
    void rs()
    {
        sz = ch[0]->sz + ch[1]->sz + cnt;
    }
} nil(0, 0, 0),LIM(INT_MAX,0,0),*NIL = &nil,*lim=&LIM;
struct Splay //伸展树结构体类型
{
    Node *root;
    int ncnt;//计算key值不同的结点数,注意已经去重了
    Node nod[MAXN];
    void init() // 首先要初始化
    {
        root = NIL;
        ncnt = 0;
    }
    void rotate(Node *x, bool d) //旋转操作,d为true表示右旋
    {
        Node *y = x->pnt;
        y->ch[!d] = x->ch[d];
        if (x->ch[d] != NIL)
            x->ch[d]->pnt = y;
        x->pnt = y->pnt;
        if (y->pnt != NIL)
        {
            if (y == y->pnt->ch[d])
                y->pnt->ch[d] = x;
            else
                y->pnt->ch[!d] = x;
        }
        x->ch[d] = y;
        y->pnt = x;
        y->rs();
        x->rs();
    }
    void splay(Node *x, Node *target) //将x伸展到target的儿子位置处
    {
        Node *y;
        while (x->pnt != target)
        {
            y = x->pnt;
            if (x == y->ch[0])
            {
                if (y->pnt != target && y == y->pnt->ch[0])
                    rotate(y, true);
                rotate(x, true);
            }
            else
            {
                if (y->pnt != target && y == y->pnt->ch[1])
                    rotate(y, false);
                rotate(x, false);
            }
        }
        if (target == NIL)
            root = x;
    }
    /************************以上一般不用修改************************/
    void insert(int key) //插入一个值
    {
        if (root == NIL)
        {
            ncnt =0;
            root = &nod[++ncnt];
            root->ch[0] = root->ch[1] = root->pnt = NIL;
            root->key = key;
            root->sz = root->cnt = 1;
            return;
        }
        Node *x = root, *y;
        while (1)
        {
            x->sz++;
            /* if (key == x->key)
             {
                 x->cnt++;
                 x->rs();
                 y = x;
                 break;
             }*/
            if (key <= x->key)
            {
                if (x->ch[0] != NIL)
                    x = x->ch[0];
                else
                {
                    x->ch[0] = &nod[++ncnt];
                    y = x->ch[0];
                    y->key = key;
                    y->sz = y->cnt = 1;
                    y->ch[0] = y->ch[1] = NIL;
                    y->pnt = x;
                    break;
                }
            }
            else
            {
                if (x->ch[1] != NIL)
                    x = x->ch[1];
                else
                {
                    x->ch[1] = &nod[++ncnt];
                    y = x->ch[1];
                    y->key = key;
                    y->sz = y->cnt = 1;
                    y->ch[0] = y->ch[1] = NIL;
                    y->pnt = x;
                    break;
                }
            }
        }
        splay(y, NIL);
    }
    Node* search(int key) //查找一个值,返回指针
    {
        if (root == NIL)
            return NIL;
        Node *x = root, *y = NIL;
        while (1)
        {
            if (key == x->key)
            {
                y = x;
                break;
            }
            else if (key > x->key)
            {
                if (x->ch[1] != NIL)
                    x = x->ch[1];
                else
                    break;
            }
            else
            {
                if (x->ch[0] != NIL)
                    x = x->ch[0];
                else
                    break;
            }
        }
        splay(x, NIL);
        return y;
    }
    Node* searchm(Node *x,bool d) //查找最小值,返回指针
    {
        if(x==NIL)
            return lim;
        Node *y = x->pnt;
        while (x->ch[d] != NIL) //遍历到最左的儿子就是最小值
        {
            x = x->ch[d];
        }
        //splay(x, y);
        return x;
    }
    void del(int key) //删除一个值
    {
        if (root == NIL)
            return;
        Node *x = search(key), *y;
        if (x == NIL)
            return;
        if (x->cnt > 1)
        {
            x->cnt--;
            x->rs();
            return;
        }
        else if (x->ch[0] == NIL && x->ch[1] == NIL)
        {
            init();
            return;
        }
        else if (x->ch[0] == NIL)
        {
            root = x->ch[1];
            x->ch[1]->pnt = NIL;
            return;
        }
        else if (x->ch[1] == NIL)
        {
            root = x->ch[0];
            x->ch[0]->pnt = NIL;
            return;
        }
        y = searchm(x->ch[1],0);
        y->pnt = NIL;
        y->ch[0] = x->ch[0];
        x->ch[0]->pnt = y;
        y->rs();
        root = y;
    }
    int rank(int key) //求结点高度
    {
        Node *x = search(key);
        if (x == NIL)
            return 0;
        return x->ch[0]->sz + 1/* or x->cnt*/;
    }
    Node* findk(int kth) //查找第k小的值
    {
        if (root == NIL || kth > root->sz)
            return NIL;
        Node *x = root;
        while (1)
        {
            if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt)
                break;
            else if (kth <= x->ch[0]->sz)
                x = x->ch[0];
            else
            {
                kth -= x->ch[0]->sz + x->cnt;
                x = x->ch[1];
            }
        }
        splay(x, NIL);
        return x;
    }
} sp;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int ans;
        scanf("%d",&ans);
        sp.init();
        sp.insert(ans);
        for(int i=0; i<n-1; i++)
        {
            int temp;
            scanf("%d",&temp);
            sp.insert(temp);
            int c;
            ans+=c=min(abs(temp-sp.searchm(sp.root->ch[0],1)->key),abs(temp-sp.searchm(sp.root->ch[1],0)->key));
           // printf("%d\n",c);
        }
        printf("%d\n",ans);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值