1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 18663 Solved: 7817
[ 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
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
该题数据bug已修复.----2016.5.15
解析:
直接用Treap求前驱和后继,然后分别计算与该数值的差,累加差的最小值即可。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cctype>
#include <queue>
using namespace std;
const int Max=51000;
const int INF=1e9+7;
int n,root=1,tot,ans;
struct Treap{int l,r,val,data;};
Treap a[Max];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline int NEW(int val)
{
a[++tot].val=val;
a[tot].data=rand();
return tot;
}
inline void build()
{
NEW(-INF);
NEW(INF);
a[1].r=2;
}
inline void zig(int &p) //左旋
{
int q=a[p].l;
a[p].l=a[q].r;a[q].r=p;p=q;
}
inline void zag(int &p) //右旋
{
int q=a[p].r;
a[p].r=a[q].l;a[q].l=p;p=q;
}
inline void Insert(int &p,int val) //插入
{
if(p==0)
{
p=NEW(val);
return;
}
if(val==a[p].val) return;
if(val<a[p].val)
{
Insert(a[p].l,val);
if(a[a[p].l].data>a[p].data) zig(p);
}
else
{
Insert(a[p].r,val);
if(a[a[p].r].data>a[p].data) zag(p);
}
}
inline int GetPre(int val) //前驱
{
int ans=1,p=root;
while(p)
{
if(a[p].val==val) return val;
if(a[p].val<val&&a[p].val>a[ans].val) ans=p;
a[p].val>val ? p=a[p].l : p=a[p].r;
}
return a[ans].val;
}
inline int GetNext(int val) //后继
{
int ans=2,p=root;
while(p)
{
if(a[p].val==val) return val;
if(a[p].val>val&&a[p].val<a[ans].val) ans=p;
a[p].val>val ? p=a[p].l : p=a[p].r;
}
return a[ans].val;
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
n=get_int();
build();
for(int i=1;i<=n;i++)
{
int x=get_int();
if(i==1) ans+=x;
else
{
int Pre=GetPre(x),Next=GetNext(x);
if(Pre==-INF&&Next!=INF) ans+=Next-x;
if(Pre!=-INF&&Next==INF) ans+=x-Pre;
if(Pre!=-INF&&Next!=INF) ans+=min(x-Pre,Next-x);
}
Insert(root,x);
}
cout<<ans<<"\n";
return 0;
}