[BZOJ1588] [HNOI2002] 营业额统计 (treap)

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

  此题数据有问题,详见讨论版

Source

Solution

  嘛,有一个测试点少了一个零。

  这道题用treap找前驱后继,比较哪个数和给定的数的差值小,再把这个数插入treap里。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct treap
 4 {
 5     int key, val, l, r, pri, siz;
 6 }a[50005];
 7 int root, ptot, p, s;
 8  
 9 void push_up(int k)
10 {
11     a[k].siz = a[a[k].l].siz + a[a[k].r].siz + 1;
12 }
13  
14 void lturn(int &k)
15 {
16     int tmp = a[k].r;
17     a[k].r = a[tmp].l, a[tmp].l = k;
18     a[tmp].siz = a[k].siz, push_up(k), k = tmp;
19 }
20  
21 void rturn(int &k)
22 {
23     int tmp = a[k].l;
24     a[k].l = a[tmp].r, a[tmp].r = k;
25     a[tmp].siz = a[k].siz, push_up(k), k = tmp;
26 }
27  
28 void insert(int &k, int x)
29 {
30     if(!k)
31     {
32         k = ++ptot, a[k].key = x, a[k].pri = rand();
33         a[k].siz = a[k].val = 1;
34         return;
35     }
36     a[k].siz++;
37     if(a[k].key == x) a[k].val++;
38     else if(x < a[k].key)
39     {
40         insert(a[k].l, x);
41         if(a[k].pri < a[a[k].l].pri) rturn(k);
42     }
43     else
44     {
45         insert(a[k].r, x);
46         if(a[k].pri < a[a[k].r].pri) lturn(k);
47     }
48 }
49  
50 void query_pro(int k, int x)
51 {
52     if(!k) return;
53     if(x < a[k].key) query_pro(a[k].l, x);
54     else p = a[k].key, query_pro(a[k].r, x);
55 }
56  
57 void query_sub(int k, int x)
58 {
59     if(!k) return;
60     if(x > a[k].key) query_sub(a[k].r, x);
61     else s = a[k].key, query_sub(a[k].l, x);
62 }
63  
64 int main()
65 {
66     int n, x, ans;
67     scanf("%d", &n), srand(n);
68     for(int i = 1; i <= n; i++)
69     {
70         if(!~scanf("%d", &x)) x = 0;
71         if(i == 1) ans = x;
72         else
73         {
74             p = -1000000000, query_pro(root, x);
75             s = 1000000000, query_sub(root, x);
76             ans += min(x - p, s - x);
77         }
78         insert(root, x);
79     }
80     printf("%d\n", ans);
81     return 0;
82 }
View Code

 

posted @ 2016-04-05 20:11  CtrlCV  阅读(250)  评论(0编辑  收藏  举报