bzoj 1588: [HNOI2002]营业额统计 (Treap)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1588

题面:

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 20273  Solved: 8709
[Submit][Status][Discuss]

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
 
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define ls t[x].ch[0]
#define rs t[x].ch[1]
const int M = 2e5 + 10;
const int inf = 0x3f3f3f3f;
map<int,int>mp;
int last[M],n,m,root,cnt;
struct node{
    int ch[2],cnt,siz,val,rd;
}t[M];

struct node1{
    int x,y;
}a[M],b[M];

bool cmp(node1 p,node1 q){
    return p.y > q.y;
}

void up(int x){
    t[x].siz = t[ls].siz + t[rs].siz+t[x].cnt;
}

void rotate(int &x,int d){
    int son = t[x].ch[d];
    t[x].ch[d] = t[son].ch[d^1];
    t[son].ch[d^1] = x; up(x); up(x=son);
}

void Insert(int &x,int val){
    if(!x){
        x = ++cnt;
        t[x].cnt = t[x].siz = 1;
        t[x].val = val,t[x].rd = rand();
        return ;
    }
    t[x].siz ++;
    if(t[x].val == val){
        t[x].cnt++; return ;
    }
    int d = t[x].val < val; Insert(t[x].ch[d],val);
    if(t[x].rd > t[t[x].ch[d]].rd) rotate(x,d);
}

void del(int &x,int val){
    if(!x) return ;
    if(t[x].val == val){
        if(t[x].cnt > 1){
            t[x].cnt--,t[x].siz--;return ;
        }
        bool d = t[ls].rd > t[rs].rd;
        if(ls == 0||rs == 0) x = ls+rs;
        else rotate(x,d),del(x,val);
    }
    else t[x].siz--,del(t[x].ch[t[x].val<val],val);
}

int rk(int x,int val){
    if(!x) return 0;
    if(t[x].val == val) return t[ls].siz+1;
    if(t[x].val > val) return rk(ls,val);
    return rk(rs,val)+t[ls].siz+t[x].cnt;
}

int kth(int root,int k){
    int x = root;
    while(1){
        if(k <= t[ls].siz) x = ls;
        else if(k > t[ls].siz+t[x].cnt)
            k -= t[ls].siz+t[x].cnt,x = rs;
        else return t[x].val;
    }
}

int pre(int x,int val){
    if(!x) return -inf;
    if(t[x].val >= val) return pre(ls,val);
    return max(pre(rs,val),t[x].val);
}

int nex(int x,int val){
    if(!x) return inf;
    if(t[x].val <= val) return nex(rs,val);
    return min(nex(ls,val),t[x].val);
}

int main()
{
    int ans,x;
    cin>>n;
    root = 0;
    cin>>ans;
    Insert(root,ans);mp[ans] = 1;
    for(int i = 2;i <= n;i ++){
        cin>>x;
        if(!mp[x])
        ans += min(x-pre(root,x),nex(root,x)-x);
        if(!mp[x]) Insert(root,x);
        mp[x]++;
    }
    cout<<ans<<endl;
}

 

posted @ 2019-04-12 17:56  冥想选手  阅读(208)  评论(0编辑  收藏  举报