BZOJ 1588: [HNOI2002]营业额统计
题目
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBDescription
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i天公司的营业额。
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
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 }