BZOJ 1588: [HNOI2002]营业额统计
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 19793 Solved: 8436
[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
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
Source
题解:
题目就是让求当前的数与前面的数最小的差值的和;
用Splay求前驱,后继然后求差值比较小的;(板题)
参考代码
1 #include<bits/stdc++.h> 2 const int INF=0x3f3f3f3f; 3 using namespace std; 4 int ans,n,t1,t2,rt,size; 5 int tr[50001][2],fa[50001],num[50001]; 6 namespace SplayTree 7 { 8 void rotate(int x,int &k) 9 { 10 int y=fa[x],z=fa[y],l,r; 11 if(tr[y][0]==x) l=0;else l=1;r=l^1; 12 if(y==k) k=x; 13 else{if(tr[z][0]==y) tr[z][0]=x;else tr[z][1]=x;} 14 fa[x]=z;fa[y]=x;fa[tr[x][r]]=y; 15 tr[y][l]=tr[x][r];tr[x][r]=y; 16 } 17 void splay(int x,int &k) 18 { 19 int y,z; 20 while(x!=k) 21 { 22 y=fa[x],z=fa[y]; 23 if(y!=k) 24 { 25 if((tr[y][0]==x)^(tr[z][0]==y))rotate(x,k); 26 else rotate(y,k); 27 } 28 rotate(x,k); 29 } 30 } 31 void ins(int &k,int x,int last) 32 { 33 if(k==0){size++;k=size;num[k]=x;fa[k]=last;splay(k,rt);return;} 34 if(x<num[k])ins(tr[k][0],x,k); 35 else ins(tr[k][1],x,k); 36 } 37 void ask_before(int k,int x)//前驱 38 { 39 if(k==0)return; 40 if(num[k]<=x){t1=num[k];ask_before(tr[k][1],x);} 41 else ask_before(tr[k][0],x); 42 } 43 void ask_after(int k,int x)//后继 44 { 45 if(k==0)return; 46 if(num[k]>=x){t2=num[k];ask_after(tr[k][0],x);} 47 else ask_after(tr[k][1],x); 48 } 49 } 50 using namespace SplayTree; 51 int main() 52 { 53 scanf("%d",&n); 54 for(int i=1;i<=n;i++) 55 { 56 int x;if(scanf("%d",&x)==EOF) x=0; 57 t1=-INF;t2=INF; 58 ask_before(rt,x); 59 ask_after(rt,x); 60 if(i!=1) ans+=min(x-t1,t2-x); 61 else ans+=x; 62 ins(rt,x,0); 63 } 64 printf("%d",ans); 65 return 0; 66 }