COGS1533.[HNOI2002]营业额统计

              ★★   输入文件:turnover.in   输出文件:turnover.out   简单对比
                时间限制:5 s   内存限制:162 MB

【题目描述】

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

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

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

 

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

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

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

【输入格式】

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

【输出格式】

输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

【样例输入】

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

【来源】

HNOI 2002

  SBT版的:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100010;
 4 int root,tot,N,ANS;
 5 int key[maxn],siz[maxn],lc[maxn],rc[maxn];
 6 void r_rotate(int &rt){
 7     int k=lc[rt];
 8     lc[rt]=rc[k];
 9     rc[k]=rt;
10     siz[k]=siz[rt];
11     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
12     rt=k;
13 }  
14 void l_rotate(int &rt){
15     int k=rc[rt];
16     rc[rt]=lc[k];
17     lc[k]=rt;
18     siz[k]=siz[rt];
19     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
20     rt=k;
21 }
22 void MAINTAIN(int &rt,bool flag){
23     if(flag==false){//rt的左子树的某子树>rt的右子树 
24         if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋 
25         else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R: 
26             l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根 
27             r_rotate(rt);//再右旋再变成以B为根 
28         }
29         else return;//平衡 
30     }
31     else{//rt的右子树的某子树>rt的左子树 
32         if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
33         else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
34             r_rotate(rc[rt]);
35             l_rotate(rt);
36         }
37         else return;
38     }
39     MAINTAIN(lc[rt],0); MAINTAIN(rc[rt],1);//检查是否满足平衡 
40     MAINTAIN(rt,1); MAINTAIN(rt,0);
41 }
42 void insert(int &rt,int v){
43     if(rt==0){//找到合适的位置插入 
44         rt=++tot; 
45         key[rt]=v;
46         lc[rt]=rc[rt]=0; siz[rt]=1;
47         return ;
48     }
49     siz[rt]++;
50     if(v<=key[rt]) insert(lc[rt],v);
51     else insert(rc[rt],v);
52     MAINTAIN(rt,v>key[rt]);//调整树结构 
53 }
54 bool find(int &rt,int v){//查找是否有 key值为 v的节点 
55     if(rt==0) return false;
56     else if(v==key[rt]) return true;
57     else if(v<key[rt]) return find(lc[rt],v);
58     else if(v>key[rt]) return find(rc[rt],v);
59 }
60 int pred(int &rt,int v){//返回比 v小的最大的数 
61     if(rt==0) return v;//要求是比v小,返回v的意思是没找到 
62     if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树 
63     else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt] 
64         int ans=pred(rc[rt],v);
65         if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回key[rt] 
66     }
67 }
68 int succ(int &rt,int v){//返回比v大的最小的数 
69     if(rt==0) return v;
70     if(v>=key[rt]) return succ(rc[rt],v);
71     else{
72         int ans=succ(lc[rt],v);
73         if(ans==v) return key[rt];
74     }
75 }
76 int main(){
77     scanf("%d",&N);
78     for(int i=1,num;i<=N;i++){
79         if(scanf("%d",&num)==EOF) num=0;
80         if(find(root,num)==true) continue;
81         if(siz[root]==0){
82             ANS+=num; insert(root,num); continue;
83         } 
84         int tmp1=pred(root,num); int tmp2=succ(root,num);
85         if(find(root,tmp1)==true&&(find(root,tmp2)==false||abs(num-tmp1)<=abs(num-tmp2))){
86             ANS+=abs(num-tmp1);
87             insert(root,num);
88         }
89         else if(find(root,tmp2)==true&&(find(root,tmp1)==false||abs(num-tmp1)>abs(num-tmp2))){
90             ANS+=abs(num-tmp2);
91             insert(root,num);
92         }
93     }
94     printf("%d",ANS);
95     return 0;
96 }

 

  Splay版的:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=200000;
  4 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
  5 int tot,root;
  6 int N,ANS;
  7 void update(int x){
  8     siz[x]=siz[lc[x]]+siz[rc[x]]+1;
  9 }
 10 void r_rotate(int x){
 11     int y=fa[x];
 12     lc[y]=rc[x]; fa[rc[x]]=y; fa[x]=fa[y];
 13     if(y==lc[fa[y]]) lc[fa[y]]=x;
 14     else rc[fa[y]]=x;
 15     fa[y]=x; rc[x]=y;
 16     update(x); update(y);
 17 }
 18 void l_rotate(int x){
 19     int y=fa[x];
 20     rc[y]=lc[x]; fa[lc[x]]=y; fa[x]=fa[y];
 21     if(y==lc[fa[y]]) lc[fa[y]]=x;
 22     else rc[fa[y]]=x;
 23     fa[y]=x; lc[x]=y;
 24     update(x); update(y);
 25 }
 26 void splay(int x,int s){
 27     int p;
 28     while(fa[x]!=s){
 29         p=fa[x];
 30         if(fa[p]==s){
 31             if(x==lc[p]) r_rotate(x);
 32             else l_rotate(x);
 33             break;
 34         }
 35         if(x==lc[p]){
 36             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
 37             else r_rotate(x),l_rotate(x);
 38         }
 39         else{
 40             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
 41             else l_rotate(x),r_rotate(x);
 42         }
 43     }
 44     if(s==0) root=x;
 45     update(x);
 46 }
 47 int find(int v){
 48     int x=root;
 49     while(x!=0){
 50         if(v<key[x]) x=lc[x];
 51         else if(v>key[x]) x=rc[x];
 52         else{
 53             splay(x,0);
 54             return x;
 55         }
 56     }
 57     return -1;
 58 }
 59 void new_node(int &x,int fath,int v){
 60     x=++tot;
 61     lc[x]=rc[x]=0; siz[x]=1;
 62     fa[x]=fath;
 63     key[x]=v;
 64 }
 65 void insert(int v){
 66     if(root==0){
 67         new_node(root,0,v);
 68         return ;
 69     }
 70     int p,x=root;
 71     while(x!=0){
 72         p=x;
 73         if(v<=key[x]) siz[x]++,x=lc[x];
 74         else siz[x]++,x=rc[x];
 75     }
 76     if(v<=key[p]) new_node(lc[p],p,v);
 77     else new_node(rc[p],p,v);
 78     splay(tot,0);
 79 }
 80 int pred(int x,int v){
 81     if(x==0) return v;
 82     if(v<=key[x]) return pred(lc[x],v);
 83     else{
 84         int ans=pred(rc[x],v);
 85         if(ans==v) return key[x];
 86         return ans;
 87     }
 88 }
 89 int succ(int x,int v){
 90     if(x==0) return v;
 91     if(v>=key[x]) return succ(rc[x],v);
 92     else{
 93         int ans=succ(lc[x],v);
 94         if(ans==v) return key[x];
 95         return ans;
 96     }
 97 }
 98 int main(){
 99     scanf("%d",&N);
100     for(int i=1,num;i<=N;i++){
101         if(scanf("%d",&num)==EOF) num=0;
102         if(find(num)!=-1) continue;
103         if(siz[root]==0){
104             ANS+=num; insert(num); continue;
105         }
106         int tmp1=pred(root,num); int tmp2=succ(root,num);
107         if(find(tmp1)!=-1&&(find(tmp2)==-1||abs(num-tmp1)<=abs(num-tmp2))){
108             ANS+=abs(num-tmp1);
109             insert(num);
110         }
111         else if(find(tmp2)!=-1&&(find(tmp1)==-1||abs(num-tmp1)>abs(num-tmp2))){
112             ANS+=abs(num-tmp2);
113             insert(num);
114         }
115     }
116     printf("%d",ANS);
117     return 0;
118 }

 

posted @ 2016-01-02 19:49  CXCXCXC  阅读(172)  评论(0编辑  收藏  举报