[洛谷 P2234] [HNOI2002] 营业额统计 --- Splay

题目描述

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:

当最小波动值越大时,就说明营业情况越不稳定。

而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。

第一天的最小波动值为第一天的营业额。

该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。

输入输出格式

输入格式
输入由文件’turnover.in’读入。

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

输出格式

输入输出样例

输入样例#1
6
5
1
2
5
4
6
输出样例#1
12
说明
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

分析

splay基本操作,只需要查找前驱和后继即可,每次其两者较小值。

代码

#include <cstdio>
#include <cstdlib>
#include <algorithm>

#define IL inline
#define inf 0x7f7f7f7f

using namespace std;

IL int read()
{
    int k = 1;
    int sum = 0;
    char c = getchar();

    for(; '0' > c || c > '9'; c = getchar())
        if(c == '-') k = -1;

    for(; '0' <= c && c <= '9'; c = getchar())
        sum =sum * 10 + c - '0';

    return sum*k;
}

struct node
{
    node *father;
    node *son[2];
    int val;

    node(int v = 0, node *f = NULL)
    {
        val = v;
        father = f;
        son[0] = son[1] = NULL;
    }
};
node *root;

IL bool son(node *f, node *s)
{
    return f->son[1] == s;
}

IL void rotate(node *p)
{
    node *f = p->father;
    node *g = f->father;
    bool x = son(f, p), y = !x;

    f->son[x] = p->son[y];

    if(p->son[y] != NULL)
        p->son[y]->father = f;

    p->son[y] = f;
    f->father = p;
    p->father = g;

    if(g != NULL)
        g->son[son(g, f)] = p;
    else
        root = p;
}

IL void splay(node *p, node *q)
{
    node *f, *g;

    for(; p->father != q;)
    {
        f = p->father;
        g = f->father;

        if(g == q)
            rotate(p);
        else
        {
            if(son(f, p) ^ son(g, f))
                rotate(p), rotate(p);
            else
                rotate(f), rotate(p);
        }
    }
}

IL bool insert(int val)
{
    bool flag=0;
    if(root == NULL)
    {
        root = new node(val, NULL);
        flag = 1;
    }

    for(node *p = root; p; p = p->son[val > p->val])
    {
        if(val == p->val) { splay(p, NULL); return flag;}
        if(p->son[val > p->val] == NULL)
        {
            p->son[val > p->val] = new node(val, p);
            flag = 1;
        }
    }
}

IL int find_pre()
{
    node *p = root->son[0];
    if(!p) return inf;
    for(; p->son[1]; p = p->son[1]);
    return root->val - p->val;
}

IL int find_nxt()
{
    node *p = root->son[1];
    if(!p) return inf;
    for(; p->son[0]; p = p->son[0]);
    return p->val - root->val;
}

int main()
{
    int n = read();
    int ans = 0;

    for(int x, i = 1; i <= n; ++ i)
    {
        x = read();
        if(!insert(x)) continue; // 可以直接跳过,ans+=0
        //printf("%d %d %d\n", x, find_pre(), find_nxt());
        if(i == 1) ans = x;
        else ans += min(find_pre(), find_nxt());
    }
    printf("%d",ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_27121257/article/details/79395238