【HNOI2002】营业额统计

传送门

题目描述

Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。

Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:

当最小波动值越大时,就说明营业情况越不稳定。

而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。

第一天的最小波动值为第一天的营业额。

该天的最小波动值=min{|该天以前某一天的营业额-该天营业额|}。

解题思路

参照黄学长qwq

首先把所有的数据都进来之后排序,然后用双向链表把相邻的数据连起来,从后向前一个一个删除,每删除一个就把它前面的跟后面的连接起来,这样就可以快速找到和每一个数差的绝对值最小的数了。

注意一个小细节,删除到最后一个数的时候特判一下。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<math.h>
 6 using namespace std;
 7 struct nod{
 8     int pos,num,l,r;
 9 }a[50005];
10 int n,match[50005],prio[50005];
11 inline bool cmp(nod x,nod y){
12     return x.num<y.num;
13 }
14 int main(){
15     scanf("%d",&n);
16     for(register int i=1;i<=n;i++){
17         scanf("%d",&a[i].num);
18         a[i].pos=i;
19     }
20     sort(a+1,a+n+1,cmp);
21     for(register int i=1;i<=n;i++){
22         a[i].l=i-1,a[i].r=i+1;
23         match[a[i].pos]=i;
24     }
25     long long ans=0;
26     a[0].num=-1000000000,a[n+1].num=1000000000;
27     for(register int i=n;i>=1;i--){
28         int now=match[i];
29         if(i==1){
30             ans+=a[now].num;
31             break;
32         }
33         ans+=min(fabs(a[now].num-a[a[now].l].num),fabs(a[now].num-a[a[now].r].num));
34         a[a[now].l].r=a[now].r;
35         a[a[now].r].l=a[now].l;
36     }
37     cout<<ans<<endl;
38 }

猜你喜欢

转载自www.cnblogs.com/Fang-Hao/p/9027059.html