BZOJ-1588 [HNOI2002]营业额统计 【splay || set】
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
题解:
就是求每个数和它前面数最小差的总和,set就可以,练习了一下splay。
代码:
【set】
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define M(a, b) memset(a, b, sizeof(a)) 5 const int N = 1e4 + 10; 6 set<int> s; 7 set<int>::iterator it, it1; 8 9 int main() { 10 int n; 11 while(~scanf("%d", &n)) { 12 int ans, x; 13 scanf("%d", &ans); 14 s.clear(); 15 s.insert(ans); 16 s.insert(INF); s.insert(-INF); 17 for (int i = 1; i < n; ++i) { 18 scanf("%d", &x); 19 it = s.lower_bound(x); 20 it1 = it; it--; 21 ans += min(x-*it, *it1-x); 22 s.insert(x); 23 } 24 printf("%d\n", ans); 25 } 26 27 return 0; 28 } 29
【splay】
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define M(a, b) memset(a, b, sizeof(a)) 5 const int N = 5e4 + 5; 6 int ch[N][2], p[N], num[N], sz, rt, pre, suc, n; 7 8 void rotate(int x, int &k) { 9 int y = p[x], z = p[y], d = ch[y][1]==x; 10 if (y == k) k = x; 11 else ch[z][ch[z][1]==y] = x; 12 p[ch[x][d^1]] = y; p[y] = x; p[x] = z; 13 ch[y][d] = ch[x][d^1]; ch[x][d^1] = y; 14 } 15 16 void splay(int x, int &k) { 17 while (x != k) { 18 int y = p[x], z = p[y]; 19 if (y != k) { 20 if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x, k); 21 else rotate(y, k); 22 } 23 rotate(x, k); 24 } 25 } 26 27 void insert(int x, int &k, int fa) { 28 if (k == 0) {k = ++sz; num[k] = x; p[k] = fa; splay(k, rt); return;} 29 if (x < num[k]) insert(x, ch[k][0], k); 30 else insert(x, ch[k][1], k); 31 } 32 33 void get_pre(int k, int x) { 34 if (k == 0) return; 35 if (num[k] <= x) {pre = num[k]; get_pre(ch[k][1], x);} 36 else get_pre(ch[k][0], x); 37 } 38 39 void get_suc(int k, int x) { 40 if (k == 0) return; 41 if (num[k] >= x) {suc = num[k]; get_suc(ch[k][0], x);} 42 else get_suc(ch[k][1], x); 43 } 44 45 int main() { 46 while (~scanf("%d", &n)) { 47 int ans, a; 48 scanf("%d", &a); ans = a; 49 insert(a, rt, 0); 50 for (int i = 1; i < n; ++i) { 51 scanf("%d", &a); 52 pre = -INF, suc = INF; 53 get_pre(rt, a); get_suc(rt, a); 54 ans += min(a-pre, suc-a); 55 insert(a, rt, 0); 56 } 57 printf("%d\n", ans); 58 } 59 60 return 0; 61 }