Description:
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。第一天的最小波动值为第一天的营业额。
该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。
Analysis:
平衡树模板题。
对于每天的波动值,要使|该天以前某一天的营业额-该天营业额|最小,只需查找它的前驱和后驱,选择最小的。就这样吧每天的波动值相加即可。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define N 50001
#define inf 0x3f3f3f3f
using namespace std;
int x,y,k,T,rt,ans,n;
inline int Min(int a,int b){
return a > b?b:a;
}
struct node{
int lc,rc,pos,fa,vl;
#define lc(x) t[x].lc
#define pos(x) t[x].pos
#define rc(x) t[x].rc
#define fa(x) t[x].fa
#define vl(x) t[x].vl
}t[N];
// left
inline void Zig(int &x){
int y = lc(x);
lc(x) = rc(y);
rc(y) = x;
x = y;
}
inline void Zag(int &x){
int y = rc(x);
rc(x) = lc(y);
lc(y) = x;
x = y;
}
inline void Insert(int &x,int val){
if(!x){
vl(x = ++T) = val;
pos(x) = rand();
return;
}
if(val < vl(x)){
Insert(lc(x),val);
if(pos(lc(x)) < pos(x)) Zig(x);
}
else{
Insert(rc(x),val);
if(pos(rc(x)) < pos(x)) Zag(x);
}
}
inline int QueryPre(int val){
int x = rt,pr = -inf;
while(x){
if(vl(x) <= val) pr = vl(x),x = rc(x);
else x = lc(x);
}
return pr;
}
inline int QuerySuf(int val){
int x = rt,sf = inf;
while(x){
if(vl(x) >= val) sf = vl(x),x = lc(x);
else x = rc(x);
}
return sf;
}
int main(){
rt = 0;
scanf("%d%d",&n,&ans);// the first day's ans
Insert(rt,ans);
for(int i = 1;i < n;++i){
int a;
scanf("%d",&a);
x = QueryPre(a),y = QuerySuf(a);
ans += Min(a - x,y - a);
Insert(rt,a);
}
printf("%d",ans);
return 0;
}