洛谷P2234 [HNOI2002] 营业额统计 [splay]

时间:2020-12-28 15:48:38

  题目传送门

营业额统计

题目描述

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:

当最小波动值越大时,就说明营业情况越不稳定。

而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。

第一天的最小波动值为第一天的营业额。

该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。

输入输出格式

输入格式:

输入由文件’turnover.in’读入。

第一行为正整数n(n<=32767) ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数ai(|ai|<=1000000) ,表示第i天公司的营业额,可能存在负数。

输出格式:

洛谷P2234 [HNOI2002] 营业额统计 [splay]

输入输出样例

输入样例#1:
6
5
1
2
5
4
6
输出样例#1:
12

说明

结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12


  分析:

  很显然的一道平衡树的题。

  每次先查询当前平衡树中是否有与询问值相同的节点,然后再比较前驱与后继与它的差值,取最优结果更新答案就行了。更新完后在把该询问值作为新节点加入平衡树中。

  这里蒟蒻打的是$splay$,速度还说的过去。

  Code:

//It is made by HolseLee on 17th Aug 2018
//Luogu.org P2234
#include<bits/stdc++.h>
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
#define Abs(a) (a)>0?(a):-(a)
using namespace std; const int inf=1e9;
const int N=1e5+;
int n,tot,root,ans;
struct Node{
int val,num,ch[],fa; void add(int x,int f)
{
ch[]=ch[]=,num=;
fa=f,val=x;
}
}t[N]; inline int read()
{
char ch=getchar();int num=;bool flag=false;
while(ch<''||ch>''){if(ch=='-')flag=true;ch=getchar();}
while(ch>=''&&ch<=''){num=num*+ch-'';ch=getchar();}
return flag?-num:num;
} inline void rotate(int x)
{
int y=t[x].fa,z=t[y].fa;
int k=(t[y].ch[]==x);
t[z].ch[t[z].ch[]==y]=x;
t[x].fa=z;
t[t[x].ch[k^]].fa=y;
t[y].ch[k]=t[x].ch[k^];
t[x].ch[k^]=y;
t[y].fa=x;
} inline void splay(int x,int tar)
{
int y,z;
while(t[x].fa!=tar){
y=t[x].fa,z=t[y].fa;
if(z!=tar){
(t[z].ch[]==y)^(t[y].ch[]==x)?rotate(x):rotate(y);
}
rotate(x);
}
if(tar==)root=x;
} inline void insert(int x)
{
int now=root,fa=;
while(now){
if(t[now].val==x)break;
fa=now,now=t[now].ch[x>t[now].val];
}
if(!now){
now=++tot;t[now].add(x,fa);
if(fa)t[fa].ch[x>t[fa].val]=now;
}else{
t[now].num++;
}
splay(now,);
} inline int lower(int x)
{
int ret=-inf,now=root;
while(now){
if(t[now].val==x){
return x;
}else if(t[now].val<x){
ret=Max(ret,t[now].val);
now=t[now].ch[];
}else if(t[now].val>x){
now=t[now].ch[];
}
}
return ret;
} inline int upper(int x)
{
int ret=inf,now=root;
while(now){
if(t[now].val==x){
return x;
}else if(t[now].val>x){
ret=Min(ret,t[now].val);
now=t[now].ch[];
}else if(t[now].val<x){
now=t[now].ch[];
}
}
return ret;
} int main()
{
n=read();
int x,ka,lu;
for(int i=;i<=n;++i){
x=read();
if(i==){
ans+=x;
}else{
ka=Abs(x-lower(x));
lu=Abs(x-upper(x));
ans+=Min(lu,ka);
}
insert(x);
}
printf("%d\n",ans);
return ;
}