BZOJ1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MB
Submit: 18891 Solved: 7956
[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
Sample Output
12
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
题解
调了一个多小时,发现是个逗比错误。。。其实挺简单的,只要维护一棵平衡树,每次查询前驱和后继即
可,我用的是splay
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 33000;
const int inf = 1<<30;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0') {if(ch=='-') f=-1;ch=getchar();}
while(ch<='9' && ch>='0') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
struct Splay{
int tot,fa[MAXN],ch[MAXN][2];
int val[MAXN];
int root;
inline bool check(int x){
return (x==ch[fa[x]][1]);
}
inline void rotate(int x){
int y=fa[x],z=fa[y];
bool chk=check(x);
fa[ch[x][chk^1]]=y;
ch[y][chk]=ch[x][chk^1];
ch[x][chk^1]=y;
fa[y]=x;fa[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
}
inline void splay(int x){
for(int f=fa[x];f;rotate(x),f=fa[x])
if(fa[f]) rotate(check(x)==check(f)?f:x);
root=x;
}
inline bool insert(int x){
if(!root){
val[++tot]=x;
root=tot;
return true;
}
int now=root,f=0;
while(1){
// cout<<1<<endl;
if(val[now]==x){
splay(now);
return false;
}
f=now;
now=ch[now][val[now]<x];
// cout<<now<<endl;
if(!now){
val[++tot]=x;
ch[f][val[f]<x]=tot;
fa[tot]=f;
splay(tot);
return true;
}
}
}
inline int get_prev(){
int cur=ch[root][0];
while(ch[cur][1]) cur=ch[cur][1];
return cur;
}
inline int get_nxt(){
int cur=ch[root][1];
while(ch[cur][0]) cur=ch[cur][0];
return cur;
}
}tree;
int n;
int ans;
int main(){
n=rd();
int x;
tree.insert(inf);tree.insert(-inf);
x=rd();ans=x;tree.insert(x);
// cout<<tree.root<<" "<<x<<endl;
for(register int i=2;i<=n;i++) {
x=rd();
if(!tree.insert(x)) continue;
int pre=tree.val[tree.get_prev()];
int nxt=tree.val[tree.get_nxt()];
// cout<<x<<" "<<pre<<" "<<nxt<<endl;
ans+=min(nxt-x,x-pre);
// cout<<"ans"<<" "<<ans<<endl;
}
printf("%d",ans);
return 0;
}