首页 > 代码库 > [HNOI2002] 营业额统计

[HNOI2002] 营业额统计

题目描述

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

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

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

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

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

输入输出格式

输入格式:

 

输入由文件’turnover.in’读入。

第一行为正整数n(n<=32767) ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数ai(|ai|<=1000000) ,表示第i天公司的营业额,可能存在负数。

 

输出格式:

 

技术分享

 

输入输出样例

输入样例#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=12

题目说的很清楚了,只是“第一天的最小波动值为第一天的营业额”这句话需要注意。那么,由于这题的特殊性,并不是最大值或最小值,而是最接近的,所以不适合用线段树等算法做。那用什么?BST是不错的选择。但是BST容易被卡啊,怎么办?写了个splay这个splay要用到的操作有Zig,Zag,splay,insert,searchpred,searchsucc。其他的不需要什么。splay这东西的精髓就是:频繁一点调用splay。还要注意的是,营业额有负数,还有0。。。

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 struct Splay{
 6     int Lid,Rid,val,fa;
 7 }T[100005];
 8 int ROOT,ans,n;
 9 int read(){
10     int x=0,f=1; char ch=getchar();
11     while (ch<0||ch>9){if (ch==-) f=-f; ch=getchar();}
12     while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
13     return x*f;
14 }
15 void Insert(int x,int v,int cnt,int ff){
16     if (T[x].val==-(1<<30)){T[x].val=v; T[x].fa=ff; return;}
17     if (v<T[x].val){
18         if (!T[x].Lid) T[x].Lid=cnt; Insert(T[x].Lid,v,cnt,x);
19     }else{
20         if (!T[x].Rid) T[x].Rid=cnt; Insert(T[x].Rid,v,cnt,x);
21     }
22 }
23 int Search_Succ(int x){
24     if (T[x].Rid){
25         for (int y=T[x].Rid; y; y=T[y].Lid) if (!T[y].Lid) return T[y].val;
26     }else if (T[x].fa&&T[T[x].fa].Lid==x) return T[T[x].fa].val; else return -(1<<28);
27 }
28 int Search_Pred(int x){
29     if (T[x].Lid){
30         for (int y=T[x].Lid; y; y=T[y].Rid) if (!T[y].Rid) return T[y].val;
31     }else if (T[x].fa&&T[T[x].fa].Rid==x) return T[T[x].fa].val; else return -(1<<28);
32 }
33 void Zig(int x){
34     int y=T[x].fa; T[y].Lid=T[x].Rid;
35     if (T[x].Rid) T[T[x].Rid].fa=y;
36     T[x].fa=T[y].fa;
37     if (T[y].fa){
38         if (y==T[T[y].fa].Lid) T[T[y].fa].Lid=x; else T[T[y].fa].Rid=x;
39     }
40     T[y].fa=x,T[x].Rid=y;
41 }
42 void Zag(int x){
43     int y=T[x].fa; T[y].Rid=T[x].Lid;
44     if (T[x].Lid) T[T[x].Lid].fa=y;
45     T[x].fa=T[y].fa;
46     if (T[y].fa){
47         if (y==T[T[y].fa].Lid) T[T[y].fa].Lid=x; else T[T[y].fa].Rid=x;
48     }
49     T[y].fa=x,T[x].Lid=y;
50 }
51 void splay(int x){
52     for (int y=T[x].fa; y; y=T[x].fa){
53         if (!T[y].fa){if (x==T[y].Lid) Zig(x); else Zag(x); break;}
54         if (x==T[y].Lid){
55             if (y==T[T[y].fa].Lid) Zig(y),Zig(x); else Zig(x),Zag(x);
56         }else{
57             if (y==T[T[y].fa].Rid) Zag(y),Zag(x); else Zag(x),Zig(x);
58         }
59     }
60     ROOT=x;
61 }
62 int main(){
63     memset(T,0,sizeof T),ROOT=1;
64     n=read(); for (int i=1; i<=n; i++) T[i].val=-(1<<30);
65     T[1].val=read(),ans=T[1].val;
66     for (int i=2; i<=n; i++){
67         int x=read();
68         Insert(ROOT,x,i,0); splay(i);
69         int suc=Search_Succ(i),pre=Search_Pred(i);
70         ans+=min(abs(suc-x),abs(pre-x));
71     }
72     printf("%d",ans);
73     return 0;
74 }
View Code

 Ps:C党还可用STL里面的set实现(代码短小而精悍)。

[HNOI2002] 营业额统计