首页 > 代码库 > BZOJ1588

BZOJ1588

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 15750  Solved: 6250
[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

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

Source

分析:

首先,将这N个元素进行排序,同时记录下原来第i个元素在排序后的位置bi. 接着,将排序后的序列建成一个双向链表。然后,按照从ana1的顺序依次处理每个元素。对于an,由于知道它在排序后的序列中的位置bn,可以查看bn的前驱pre[bn]与后继next[bn]所指的数。很显然,由于数据在双向链表中是有序的,所以最小波动值必然是an与这两个数中的某一个的差的绝对值。当然,如果前驱或后继为空,就不需要考虑相应的位置了。处理完an后,我们把它从双向链表中删除(由前文可知,这一步操作的时间复杂度仅为O(1)),接着处理an-1这样,每当处理ai时,ai+1ai+2……, an已被从双向链表中删除,而此时bi的前驱与后继所指的数就等于将a1a2……, ai排序后ai的前驱与后继。整个算法分为排序,建表与处理三部分。很显然,建表与处理的时间复杂度均为O(N),所以此算法的时间复杂度与排序的时间复杂度同阶,为O(Nlog2N).

技术分享
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "string"
 5 #include "algorithm"
 6 using namespace std;
 7 const int maxn=32767+10;
 8 int n;
 9 typedef struct{
10     int num,pos;
11     int L,R;
12 }Node;
13 Node p[maxn];
14 int b[maxn],c[maxn];
15 bool cmp(Node x,Node y){
16     return x.num<y.num;
17 }
18 int main()
19 {
20     while(cin>>n)
21     {
22         memset(p,0,sizeof(p));
23         memset(b,0,sizeof(b));
24         for(int i=1;i<=n;i++){
25             cin>>p[i].num;
26             c[i]=p[i].num;
27             p[i].pos=i;
28         }
29         sort(p+1,p+1+n,cmp);
30         for(int i=1;i<=n;i++)
31         b[p[i].pos]=i;
32         for(int i=1;i<=n;i++){
33             p[i].L=i-1;
34             p[i].R=i+1;
35         }
36         p[n].R=0;
37         int ans=c[1];
38         for(int i=n;i>1;i--){
39             int x=b[i];
40             if(p[x].L&&p[x].R){
41                 ans+=min((p[x].num-p[p[x].L].num),(p[p[x].R].num-p[x].num));
42                 p[p[x].L].R=p[x].R;
43                 p[p[x].R].L=p[x].L;
44             }else if(!p[x].L){
45                 ans+=(p[p[x].R].num-p[x].num);
46                 p[p[x].R].L=0;
47             }else{
48                 ans+=(p[x].num-p[p[x].L].num);
49                 p[p[x].L].R=0;
50             }
51         }
52         cout<<ans<<endl;
53     }
54     return 0;
55 }
View Code

 

BZOJ1588