【Bzoj1588】营业额统计

7 篇文章 0 订阅
4 篇文章 0 订阅

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 14967   Solved: 5850
[ Submit][ Status][ Discuss]

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


除了第一次意外,每次都查询前驱后继,因为有负数的缘故,查询时要把Inf赋大一点,开始就是因为赋小了各种RE,WA,$!$!@&*T%@%*(!@%@。之后的就只要取min((x-pre),(sub-x))就行了。

#include <cstdio>
#include <algorithm>

using namespace std;

const int maxx = 50000 + 100;
const int maxn = 1000000 + 100;
const int Inf = 1000000000 + 100;
int num,n,tot,root,Ans1,Ans2,x;
bool done[maxn];

struct Node{
    int lc,rc;
    int v,fix;
    int size,cnt;
}T[maxx];

void update(int i){
    T[i].size = T[T[i].lc].size + T[T[i].rc].size + 1;
}

void lturn(int &i){
    int t = T[i].rc;
    T[i].rc = T[t].lc;
    T[t].lc = i;
    T[t].size = T[i].size;
    update(i);
    i = t;
}

void rturn(int &i){
    int t = T[i].lc;
    T[i].lc = T[t].rc;
    T[t].rc = i;
    T[t].size = T[i].size;
    update(i);
    i = t;
}

void insert(int &i,int x){
    if(i == 0){
        num++;
        i = num;
        T[i].size = 1;
        T[i].v = x;
        T[i].fix = rand();
        return;
    }
    T[i].size++;
    if(x < T[i].v){
        insert(T[i].lc,x);
        if(T[T[i].lc].fix < T[i].fix) rturn(i);
    }
    else{
        insert(T[i].rc,x);
        if(T[T[i].rc].fix < T[i].fix) lturn(i);
    }
}

void Query_pre(int i,int x){
    if(i == 0) return;
    if(T[i].v <= x){
        Ans1 = T[i].v;
        Query_pre(T[i].rc,x);
    }
    else Query_pre(T[i].lc,x);
}

void Query_sub(int i,int x){
    if(i == 0) return;
    if(T[i].v >= x){
        Ans2 = T[i].v;
        Query_sub(T[i].lc,x);
    }
    else Query_sub(T[i].rc,x);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        Ans1 = -Inf;
		Ans2 = Inf;
		Query_pre(root,x);
        Query_sub(root,x);
        if(i!=1)
            tot += min((x-Ans1),(Ans2-x));
        else
        	tot += x;
        insert(root,x);
    }
    printf("%d\n",tot);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值