bzoj 1588: [HNOI2002]营业额统计
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3737 Solved: 1154 [Submit][Status][Discuss]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
Source
附网站 http://www.lydsy.com/JudgeOnline/problem.php?id=1588 题解:最近在学splay...正好百度到bzoj的题 拿来刷..此题坑处多多 算法就是裸的splay 每次插入完毕之后找前驱和后继【不知道的自行百度】... 然后取差最小的..需要注意的是 插入前几个点的时候 可能不存在前驱 或后继 需要判断一下... 还有比较争议的就是第一个数是取绝对值还是 原值..题目没说...怎么写都A= =还好没有第一个数是负数的 数据... 然后最吐槽的是...数据有两个点 ms少一行...所以..读入的时候 写成 if(scanf("%d",&d) == EOF) d= 0; ...然后就木了...下面是code【可能有坑 慎入】C++语言: 高亮代码由发芽网提供
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef struct{
int l,r,k,f,c;
}node;
int root=1,n,pos,fa,num=0,key,ans,k1,k2,d;
node t[1000000];
int abss(int k){
return(k>0?k:-k);
}
void zig(int k){
int fa;
fa=t[k].f;
t[fa].c=t[fa].c-t[k].c+t[t[k].r].c;
t[k].c+=t[fa].c-t[t[k].r].c;
t[fa].l=t[k].r;
if(t[k].r!=-1) t[t[k].r].f=fa;
t[k].r=fa;t[k].f=t[fa].f;
if(t[t[fa].f].l==fa) t[t[fa].f].l=k;
else t[t[fa].f].r=k;
t[fa].f=k;
}
void zag(int k){
fa=t[k].f;
t[fa].c=t[fa].c-t[k].c+t[t[k].l].c;
t[k].c+=t[fa].c-t[t[k].l].c;
t[fa].r=t[k].l;
if(t[k].l!=-1) t[t[k].l].f=fa;
t[k].l=fa;t[k].f=t[fa].f;
if(t[t[fa].f].l==fa) t[t[fa].f].l=k;
else t[t[fa].f].r=k;
t[fa].f=k;
}
void splay(int k){
int fa;
while(t[k].f!=-1){
fa=t[k].f;
if(fa==root){
if(t[fa].l==k) zig(k);
else zag(k);
}else
if(t[t[fa].f].l==fa){
if(t[fa].l==k) zig(fa),zig(k);
else zag(k),zig(k);
}else{
if(t[fa].r==k) zag(fa),zag(k);
else zig(k),zag(k);
}
}
root=k;
}
void insert(int key){
t[++num].k=key;
if(num==1) return;
pos=root;
while(((t[pos].f!=-1)||(pos==root))&&(pos!=-1)){
if(pos!=-1) fa=pos;
if(t[pos].k>key) pos=t[pos].l;
else pos=t[pos].r;
}
t[num].f=fa;
if(t[fa].k>key) t[fa].l=num;
else t[fa].r=num;
while(fa!=-1){
t[fa].c++;
fa=t[fa].f;
}
splay(num);
}
int search(int key){
pos=root;
while((t[pos].k!=key)&&(pos!=-1)){
if(t[pos].k>key) pos=t[pos].l;
else pos=t[pos].r;
}
if(t[pos].k==key){
splay(pos);
return(pos);
}
else return(0);
}
int maxnum(int pos){
if(t[pos].r==-1) return(pos);
while((t[pos].r!=-1)&&(pos!=-1)) pos=t[pos].r;
return(pos);
}
int minnum(int pos){
if(t[pos].l==-1) return(pos);
while((t[pos].l!=-1)&&(pos!=-1)) pos=t[pos].l;
return(pos);
}
int succ(int k){
if(t[k].r!=-1) return(minnum(t[k].r));
fa=t[k].f;
while((k==t[fa].r)&&(fa!=-1)){
k=fa;fa=t[k].f;
}
if(k!=fa) return(fa);
else return(-1);
}
int pred(int k){
if(t[k].l!=-1) return(maxnum(t[k].l));
fa=t[k].f;
while((k==t[fa].l)&&(fa!=-1)){
k=fa;
fa=t[k].f;
}
if(k!=fa) return(fa);
else return(-1);
}
int main(){
scanf("%d",&n);
memset(t,-1,sizeof(t));
for(int i=1;i<=n;i++) t[i].k=-0x3fffffffffLL,t[i].c=1;
for(int i=1;i<=n;i++){
if(scanf("%d",&d) == EOF) d= 0;
insert(d);
if(i==1) ans+=d;
else{
k1=pred(i);k2=succ(i);
if(k1==-1) {ans+=abss(t[k2].k-d);continue;}
if(k2==-1) {ans+=abss(t[k1].k-d);continue;}
k1=abss(t[k1].k-d);k2=abss(t[k2].k-d);
ans+=k1<k2?k1:k2;
}
}
cout<<ans<<endl;
}