题目描述
Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助 Tiger 来计算这一个值。
我们定义,一天的最小波动值 = \min\{|\text{该天以前某一天的营业额}-\text{该天营业额}|\}min{∣该天以前某一天的营业额−该天营业额∣}。
特别地,第一天的最小波动值为第一天的营业额。
输入格式
第一行为正整数 nn(n \leq 32767n≤32767) ,表示该公司从成立一直到现在的天数,接下来的 nn 行每行有一个整数 a_iai(|a_i| \leq 10^6∣ai∣≤106) ,表示第 ii 天公司的营业额,可能存在负数。
输出格式
输出一个正整数,即每一天最小波动值的和,保证结果小于 2^{31}231。
输入输出样例
输入 #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=125+∣1−5∣+∣2−1∣+∣5−5∣+∣4−5∣+∣6−5∣=5+4+1+0+1+1=12
上代码:
#include<cstdio>
#include<set>
using namespace std;
typedef multiset<int>::iterator iter;
//定义iter类型,免去每次打一大串的苦恼
const int inf=0x7fffffff;
//定义无限大,0x7fffffff为16进制
int n,x,ans;
multiset<int>s;
inline int min(int a,int b){return a<b?a:b;}
inline int abs(int x){return x<0?-x:x;}
int main(){
s.insert(inf);s.insert(-inf);
//插入正无穷和负无穷,防止迭代器访问到一些奇奇怪怪的内存
scanf("%d",&n);
scanf("%d",&x);s.insert(x);ans=x;
//第一个单独考虑
while(--n){
scanf("%d",&x);
iter it=s.insert(x);
//插入x,并返回x在s中的位置(迭代器)
it--;
iter l=it;
it++;it++;
iter r=it;
it--;
//迭代器只支持++,--运算符,所以看上去很麻烦。。
//其实l就是上一个数,r是下一个数(在s中)
if(*l==-inf)ans+=abs(x-*r);
//在最前面
if(*r==inf)ans+=abs(x-*l);
//在最后面
if(*l!=-inf&&*r!=inf)ans+=min(abs(x-*r),abs(x-*l));
//一般情况
}
printf("%d",ans);
}