BZOJ 1588: [HNOI2002]营业额统计

题目

1588: [HNOI2002]营业额统计

Time Limit: 5 Sec  Memory Limit: 162 MB

Description

营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。  输入输出要求

Input

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

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


此题数据有问题,详见讨论版http://www.lydsy.com/JudgeOnline/wttl/wttl.php?pid=1588

 

Source

 

题解

这道题目同样是一道寻找前驱和后继的题目,我们同样使用SBT来维护Orz~有一个坑点就是这道题目的数据最后可能有残缺,直接按0来算就可以了~

代码

  1 /*Author:WNJXYK*/
  2 #include<cstdio>
  3 using namespace std;
  4 
  5 const int Maxn=1000000;
  6 const int Zero=1000000;
  7 const int Inf=1e9;
  8 bool vis[Maxn*2+10];
  9 struct SBT{
 10     int left;
 11     int right;
 12     int size;
 13     int key;
 14 }; 
 15 SBT tree[2*Maxn+10];
 16 int root,cnt;
 17 
 18 inline void rotate_l(int &x){
 19     int y=tree[x].right;
 20     tree[x].right=tree[y].left;
 21     tree[y].left=x;
 22     tree[y].size=tree[x].size;
 23     tree[x].size=1+tree[tree[x].left].size+tree[tree[x].right].size;
 24     x=y;
 25 }
 26 
 27 inline void rotate_r(int &x){
 28     int y=tree[x].left;
 29     tree[x].left=tree[y].right;
 30     tree[y].right=x;
 31     tree[y].size=tree[x].size;
 32     tree[x].size=tree[tree[x].left].size+1+tree[tree[x].right].size;
 33     x=y; 
 34 }
 35 
 36 void maintain(int &x,bool flag){
 37     //printf("MainTain %d\n",x);
 38     if (flag==false){
 39         if (tree[tree[tree[x].left].left].size>tree[tree[x].right].size){
 40             rotate_r(x);
 41         }
 42         else if (tree[tree[tree[x].left].right].size>tree[tree[x].right].size){
 43             rotate_l(tree[x].left);
 44             rotate_r(x);
 45         }else return ;
 46     }else{
 47         if (tree[tree[tree[x].right].right].size>tree[tree[x].left].size){
 48             rotate_l(x);
 49         }else if (tree[tree[tree[x].right].left].size>tree[tree[x].left].size){
 50             rotate_r(tree[x].right);
 51             rotate_l(x);
 52         }else return ;
 53     }
 54     maintain(tree[x].left,false);
 55     maintain(tree[x].right,true);
 56     maintain(x,true);
 57     maintain(x,false);
 58 }
 59 void insert(int &x,int sp){
 60     if (!x){
 61         x=++cnt;
 62         tree[x].left=tree[x].right=0;
 63         tree[x].size=1;
 64         tree[x].key=sp;
 65     }else{
 66         tree[x].size++;
 67         if (sp<tree[x].key){
 68             insert(tree[x].left,sp);
 69         }else{
 70             insert(tree[x].right,sp);
 71         }
 72         maintain(x,sp>=tree[x].key);
 73     }
 74 }
 75 
 76 int del(int &x,int sp){
 77     tree[x].size--;
 78     if (sp==tree[x].key || ( sp<tree[x].key && tree[x].left==0) || (sp>tree[x].key && tree[x].right==0)){
 79         int y=tree[x].key;
 80         if (tree[x].left==0 ||tree[x].right==0){
 81             x=tree[x].left+tree[x].right;
 82             }else{
 83             tree[x].key=del(tree[x].left,tree[x].key+1);
 84         }
 85         return y;
 86     }else{
 87         if (sp<tree[x].key){
 88             return del(tree[x].left,sp);
 89         }else{
 90             return del(tree[x].right,sp);
 91         }
 92     }
 93 }
 94 
 95 inline int getMax(){
 96     int i;
 97     for (i=root;tree[i].right;i=tree[i].right);
 98     return tree[i].key;
 99 }
100 
101 inline int getMin(){
102     int i;
103     for (i=root;tree[i].left;i=tree[i].left);
104     return tree[i].key;
105 }
106 
107 int rank(int &x,int sp){
108     if (sp<tree[x].key){
109         return rank(tree[x].left,sp);
110     }else if (sp>tree[x].key){
111         return rank(tree[x].right,sp)+tree[tree[x].left].size+1;
112     }
113     return tree[tree[x].left].size+1;
114 }
115 
116 int select(int &x,int rak){
117     int rk=tree[tree[x].left].size+1;
118     if (rak<rk){
119         return select(tree[x].left,rak);
120     }else if (rak>rk){
121         return select(tree[x].right,rak-rk);
122     }
123     return tree[x].key;
124 }
125 
126 int pred(int &x,int y,int sp){
127     if (x==0) return y;
128     if (tree[x].key<sp){
129         return pred(tree[x].right,x,sp);
130     }
131     return pred(tree[x].left,y,sp);
132 }
133 
134 int succ(int &x,int y,int sp){
135     if (x==0) return y;
136     if (tree[x].key>sp){
137         return succ(tree[x].left,x,sp);
138     }
139     return succ(tree[x].right,y,sp);
140 }
141 
142 inline int abs(int x){
143     if (x<0) return -x;
144     return x;
145 }
146 
147 inline int remin(int a ,int b){
148      if (a<b) return a;
149      return b;
150 }
151 
152 inline void init(){
153     root=cnt=0;
154 }
155 
156 int main(){
157     init();
158     int n;
159     int Ans;
160     scanf("%d%d",&n,&Ans);
161     insert(root,Ans);vis[Ans+Zero]=true;
162     int tmp,f1,f2;
163     for (int i=2;i<=n;i++){
164         if (scanf("%d",&tmp)==EOF) tmp=0;
165         if (vis[tmp+Zero]) continue;
166         vis[tmp+Zero]=true;
167         f1=pred(root,0,tmp);
168         if (f1!=0) f1=tree[f1].key;else f1=-Inf;
169         f2=succ(root,0,tmp);
170         if (f2!=0) f2=tree[f2].key;else f2=-Inf;
171         Ans+=remin(abs(f1-tmp),abs(f2-tmp));
172         insert(root,tmp);
173     }
174     printf("%d\n",Ans);
175     return 0;
176 }
View Code

 

posted @ 2014-11-23 20:36  WNJXYK  阅读(163)  评论(0编辑  收藏  举报

WNJXYK-我今年一定要努力!