营业额统计
Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。
分析营业情况是一项相当复杂的工作。
由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。
经济管理学上定义了一种最小波动值来衡量这种情况。
设第i天的营业额为ai,则第i天(i≥2)的最小波动值fi被定义为:
当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。
你的任务就是编写一个程序帮助Tiger来计算这一个值。
第一天的最小波动值为第一天的营业额a1。
输入格式
第一行为正整数n,表示该公司从成立一直到现在的天数。
接下来的n行每行有一个整数ai(有可能有负数) ,表示第i天公司的营业额。
输出格式
输出一个正整数,表示最小波动值的和。
数据范围
输入样例:
6
5
1
2
5
4
6
输出样例:
12
样例解释
在样例中,5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12。
写了上一道题再写这道题好多了,这道题让目标值最小,明显就是在最接近x的两个数之间做差取绝对值。分别是最大的最小值,和最小的最大值。也就是前驱和后继。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=33010,inf=1e7;
struct Node{
int l,r;
int key,val;
}tr[N];
int root,idx;
int get_node(int key)
{
tr[++idx].key=key;
tr[idx].val=rand();
return idx;
}
void build()
{
get_node(-inf),get_node(inf);
root=1,tr[root].r=2;
}
int zig(int &p)
{
int q=tr[p].l;
tr[p].l=tr[q].r,tr[q].r=p,p=q;
}
int zag(int &p)
{
int q=tr[p].r;
tr[p].r=tr[q].l,tr[q].l=p,p=q;
}
void insert(int &p,int key)
{
if(!p) p=get_node(key);
else if(tr[p].key==key) return;
else if(tr[p].key>key){
insert(tr[p].l,key);
if(tr[tr[p].l].val>tr[tr[p].r].val) zig(p);
}else{
insert(tr[p].r,key);
if(tr[tr[p].r].val>tr[tr[p].l].val) zag(p);
}
}
int get_prev(int p,int key)
{
if(!p) return -inf;
else if(tr[p].key>key){
return get_prev(tr[p].l,key);
}
return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int p,int key)
{
if(!p) return inf;
else if(tr[p].key<key) return get_next(tr[p].r,key);
return min(tr[p].key,get_next(tr[p].l,key));
}
signed main()
{
build();
int n; scanf("%lld",&n);
int res=0;
for(int i=1;i<=n;i++){
int x; scanf("%lld",&x);
if(i==1) res+=x;
else res+=min(x-get_prev(root,x),get_next(root,x)-x);
insert(root,x);
}
cout<<res<<endl;
}
来源:CSDN
作者:行走天涯的豆沙包
链接:https://blog.csdn.net/weixin_42979819/article/details/104216226