BZOJ1588 HNOI2002 营业额统计 [Splay入门题]

时间:2021-08-23 16:36:40

[HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 4128  Solved: 1305

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

splay

看着就晕,姑且半抄着代码写了下来,以后慢慢刷熟练度好了

 /**/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int INF=;
const int mxn=;
int v[mxn],ch[mxn][],fa[mxn],root=,cnt=;
int t1,t2;
int n;
void rotate(int x,int &k){
int y=fa[x],z=fa[y];
int l,r;
if(ch[y][]==x) l=; else l=;
r=l^;
if(y==k)k=x;
else{
if(ch[z][]==y) ch[z][]=x;
else ch[z][]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];
ch[x][r]=y;
}
void splay(int x,int &k){
int y,z;
while(x!=k){
y=fa[x];z=fa[y];
if(y!=k){
if((ch[y][]==x)^(ch[z][]==y))rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
return;
}
void insert(int &k,int val,int father){
if(!k){
k=++cnt;
v[k]=val;
fa[k]=father;
splay(k,root);
return;
}
if(val<v[k]) insert(ch[k][],val,k);
else if(val>v[k]) insert(ch[k][],val,k);
}
void ask_1(int k,int x){//求前驱
if(!k)return;
if(x>=v[k]){
t1=v[k];
ask_1(ch[k][],x);
}else ask_1(ch[k][],x);
return;
}
void ask_2(int k,int x){//求前驱
if(!k)return;
if(x<=v[k]){
t2=v[k];
ask_2(ch[k][],x);
}else ask_2(ch[k][],x);
return;
}
int main(){
scanf("%d",&n);
int i,j,x;
bool first=;
int ans=;
for(i=;i<=n;i++){
scanf("%d",&x);
t1=-INF;
t2=INF;
if(first){
first=;
ans+=x;
}
else {
ask_1(root,x);
ask_2(root,x);
ans+=min(x-t1,t2-x);
}
insert(root,x,);
}
printf("%d\n",ans);
return ;
}