[HNOI2002]营业额统计
Description
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:该天的最小波动值= min { | 该天以前某一天的营业额-该天的营业额 | }当最小波动值越大时,就说明营业情况越不稳定。而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
注:第一天的最小波动值为第一天的营业额。
数据范围:天数n≤32767,每天的营业额ai≤1,000,000。最后结果T≤2^31
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数
接下来的n行每行有一个正整数 ,表示第i天公司的营业额
Output
输出文件仅有一个正整数,即Sigma(每天的最小波动值)。结果小于2^31
Sample Input
6
5
1
2
5
4
6
Sample Output
12
HNIT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
splay模板,每次插入一个点之后找到前驱后继,取差的绝对值最小的即可
关于本人splay代码操作详解请参考浅谈算法——splay
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=5e4;
struct Splay{
#define T(x) (tree[f[x]][1]==x)
int f[N+10],tree[N+10][2],val[N+10];
int root,len;
void move(int x){
int fa=f[x],son=tree[x][T(x)^1];
tree[x][T(x)^1]=fa;
tree[fa][T(x)]=son;
if (son) f[son]=fa;
f[x]=f[fa];
if (f[x]) tree[f[x]][T(fa)]=x;
f[fa]=x;
}
void splay(int x){
while (f[x]){
if (f[f[x]]) T(x)==T(f[x])?move(f[x]):move(x);
move(x);
}
root=x;
}
void insert(int x){
val[++len]=x;
if (!root){root=len;return;}
int i=root;
while (1){
if (x<=val[i]){
if (!tree[i][0]){f[len]=i,tree[i][0]=len;break;}
i=tree[i][0];
}else{
if (!tree[i][1]){f[len]=i,tree[i][1]=len;break;}
i=tree[i][1];
}
}
splay(len);
}
int get_pre(){
int x=tree[root][0];
while (tree[x][1]) x=tree[x][1];
return x;
}
int get_suc(){
int x=tree[root][1];
while (tree[x][0]) x=tree[x][0];
return x;
}
int get(){
int ans1=get_pre(),ans2=get_suc();
if (!(ans1||ans2)) return val[root];
if (ans1&&ans2) return min(abs(val[root]-val[ans1]),abs(val[root]-val[ans2]));
return abs(val[root]-val[ans1]-val[ans2]);
}
}T;
int main(){
int n=read(),ans=0;
for (int i=1;i<=n;i++){
int x=read();
T.insert(x);
ans+=T.get();
}
printf("%d\n",ans);
return 0;
}