bzoj1588 [HNOI2002]营业额统计(Treap)

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 11485  Solved: 4062
[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


此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588

Source

 

【思路】

       Treap。

       构造一个集合S,对于每一个x提供查找S中比x小的最大的数和比x大的最小的数。

       可用Treap完成(此题原数据可过,bzoj上的数据不再深究)。

【代码】

 

 1 #include<cstdio>
 2 #include<ctime>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<iostream>
 6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 7 using namespace std;
 8 
 9 struct Node{
10     Node* ch[2];
11     int v,r;
12     Node(int w) :v(w) { ch[0]=ch[1]=NULL; r=rand(); }
13     int cmp(int x) const {
14         if(x==v) return -1;  return x<v? 0:1;
15     }
16 };
17 Node* root;
18 
19 void rotate(Node* &o,int d) {
20     Node*k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o=k;
21 }
22 void insert(Node* &o,int x) {
23     if(o==NULL) o=new Node(x);
24     else {
25         int d=o->cmp(x); if(d==-1) return ;
26         insert(o->ch[d],x);
27         if(o->ch[d]->r > o->r) rotate(o,d^1);
28     }
29 }
30 void removetree(Node* &o) {
31     if(o->ch[0]!=NULL) removetree(o->ch[0]);
32     if(o->ch[1]!=NULL) removetree(o->ch[1]);
33     delete o , o=NULL;
34 }
35 void query1(Node* o,int x,int& ans) {
36     if(o==NULL) return ;
37     if(o->v <= x) { ans=o->v; query1(o->ch[1],x,ans); }
38     else query1(o->ch[0],x,ans);
39 }
40 void query2(Node* o,int x,int& ans) {
41     if(o==NULL) return ;
42     if(o->v >= x) { ans=o->v; query2(o->ch[0],x,ans); }
43     else query2(o->ch[1],x,ans);
44 }
45 int n;
46 int abs(int x) { return x<0? -x:x; }
47 
48 int main() {
49     //freopen("in.in","r",stdin);
50     //freopen("out.out","w",stdout);
51     while(scanf("%d",&n)==1) {
52         int x,ans=0,tmp,ta;
53         for(int i=0;i<n;i++) {
54             if(scanf("%d",&x)==EOF) x=0;
55             if(!i) { ans+=x; root=new Node(x); continue; }
56             query1(root,x,tmp);
57             ta=abs(x-tmp);
58             query2(root,x,tmp);
59             ta=min(ta,abs(x-tmp));
60             insert(root,x);
61             ans+=ta;
62         }
63         printf("%d\n",ans);
64         removetree(root);
65     }
66     return 0;
67 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值