1. 程式人生 > >bzoj1588: [HNOI2002]營業額統計(平衡樹)

bzoj1588: [HNOI2002]營業額統計(平衡樹)

原題連結

題目描述:營業額統計 Tiger最近被公司升任為營業部經理,他上任後接受公司交給的第一項任務便是統計並分析公司成立以來的營業情況。 Tiger拿出了公司的賬本,賬本上記錄了公司成立以來每天的營業額。分析營業情況是一項相當複雜的工作。由於節假日,大減價或者是其他情況的時候,營業額會出現一定的波動,當然一定的波動是能夠接受的,但是在某些時候營業額突變得很高或是很低,這就證明公司此時的經營狀況出現了問題。經濟管理學上定義了一種最小波動值來衡量這種情況: 該天的最小波動值 當最小波動值越大時,就說明營業情況越不穩定。 而分析整個公司的從成立到現在營業情況是否穩定,只需要把每一天的最小波動值加起來就可以了。你的任務就是編寫一個程式幫助Tiger來計算這一個值。 第一天的最小波動值為第一天的營業額。

輸入格式:第一行為正整數 ,表示該公司從成立一直到現在的天數,接下來的n行每行有一個整數(有可能有負數) ,表示第i
天公司的營業額。天數n<=32767,每天的營業額ai <= 1,000,000。最後結果T<=2^31。

輸出格式:輸出檔案僅有一個正整數,即Sigma(每天最小的波動值) 。結果小於2^31 。

輸入樣例
6
5
1
2
5
4
6

輸出樣例
12

解析:平衡樹的模板題。
   每次求一次前驅和後繼求一個最小值相加即可。

程式碼如下:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn = 40005;
int n, root, ans;
int a[maxn], size[maxn], c[maxn], pri[maxn], cnt, lson[maxn], rson[maxn];

int read(void) {
    char c; while (c = getchar(), (c < '0' || c > '9') && c != '-'); int x = 0, y = 1;
    if (c == '-') y = -1; else x = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x * y; 
}

int rand(){
    static int seed = 2333;
    return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
}

void up(int k) {
    size[k] = size[lson[k]] + size[rson[k]] + c[k];
}

void zig(int &k) {
    int v = rson[k]; rson[k] = lson[v]; lson[v] = k;
    size[v] = size[k]; up(k); k = v;
}

void zag(int &k) {
    int v = lson[k]; lson[k] = rson[v]; rson[v] = k;
    size[v] = size[k]; up(k); k = v;
}

void insert(int &k, int x) {
    if (k == 0) {
      k = ++ cnt;
      a[k] = x; size[k] = c[k] = 1; pri[k] = rand();
      return;
    }
    size[k] ++;
    if (a[k] == x) c[k] ++;
    else if (x > a[k]) {
      insert(rson[k], x);
      if (pri[rson[k]] < pri[k]) zig(k);
    }
    else {
      insert(lson[k], x);
      if (pri[lson[k]] < pri[k]) zag(k);
    }
}

int query_pre(int &k, int x) { //求前驅 
    if (k == 0) return -2e9;
    if (x >= a[k]) return max(a[k], query_pre(rson[k], x));
    else return query_pre(lson[k], x);
}

int query_next(int &k, int x) { //求後繼 
    if (k == 0) return 2e9;
    if (x <= a[k]) return min(a[k], query_next(lson[k], x));
    else return query_next(rson[k], x);
}

int main() {
    n = read();
      for (int i = 1; i <= n; ++ i) {
        int x = read();
        int tmpx = query_pre(root, x), tmpy = query_next(root, x);
        if (tmpx == -2e9 && tmpy == 2e9) ans += x;
        else if (tmpx == -2e9) ans += abs(x - tmpy);
        else if (tmpy == 2e9) ans += abs(x - tmpx);
        else ans += min(abs(x - tmpx), abs(x - tmpy));
        insert(root, x);
      }
    printf("%d", ans);
    return 0; 
}