题目
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
天数n<=32767,每天的营业额ai <= 1,000,000。最后结果T<=2^31
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
分析
按天数顺序将每天权值依次加入线段树中权值所在位置,每一次波折即为在此点之前的最大值和此点的差与在此点之后的最小值与此点的差的最小值。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int inf=1e9+7;
map<int,int>id;
map<int,int>back;
int d[3][440000],a[110000],b[110000];
inline int read(){
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
return f*x;
}
inline void add(int le,int ri,int k,int wh){
d[0][wh]=max(d[0][wh],k),d[1][wh]=min(d[1][wh],k);
if(le==ri)return;
int mid=(le+ri)>>1;
if(mid>=k)add(le,mid,k,wh*2);
else add(mid+1,ri,k,wh*2+1);
}
inline int q(int le,int ri,int x,int y,int wh,int mm){
if(mm==0){
if(le>=x&&ri<=y)return d[0][wh];
int ans=0,mid=(le+ri)>>1;
if(mid>=x)ans=max(ans,q(le,mid,x,y,wh*2,mm));
if(mid<y)ans=max(ans,q(mid+1,ri,x,y,wh*2+1,mm));
return ans;
}else {
if(le>=x&&ri<=y)return d[1][wh];
int ans=inf,mid=(le+ri)>>1;
if(mid>=x)ans=min(ans,q(le,mid,x,y,wh*2,mm));
if(mid<y)ans=min(ans,q(mid+1,ri,x,y,wh*2+1,mm));
return ans;
}
}
int main()
{ int n,m,i,j,k,ans=0,sum=0;
for(i=1;i<=400000;i++)d[1][i]=inf;
n=read();
for(i=1;i<=n;i++){
a[i]=read();
b[i]=a[i];
}
sort(b+1,b+n+1);
for(i=1;i<=n;i++)
if(!id[b[i]]){
id[b[i]]=++sum;
back[sum]=b[i];
}
ans+=a[1];
add(1,sum,id[a[1]],1);
for(i=2;i<=n;i++){
int tot=inf,x=q(1,sum,1,id[a[i]],1,0),y=q(1,sum,id[a[i]],sum,1,1);
if(x>0)tot=min(tot,abs(back[x]-a[i]));
if(y<inf)tot=min(tot,abs(back[y]-a[i]));
ans+=tot;
add(1,sum,id[a[i]],1);
}
printf("%d
",ans);
return 0;
}