[洛谷P2234, HNOI2002]營業額統計, fhq-treap

題目描述

Tiger最近被公司升任爲營業部經理,他上任後接受公司交給的第一項任務便是統計並分析公司成立以來的營業情況。

Tiger拿出了公司的賬本,賬本上記錄了公司成立以來每天的營業額。分析營業情況是一項相當複雜的工作。由於節假日,大減價或者是其他情況的時候,營業額會出現一定的波動,當然一定的波動是能夠接受的,但是在某些時候營業額突變得很高或是很低,這就證明公司此時的經營狀況出現了問題。經濟管理學上定義了一種最小波動值來衡量這種情況:

當最小波動值越大時,就說明營業情況越不穩定。

而分析整個公司的從成立到現在營業情況是否穩定,只需要把每一天的最小波動值加起來就可以了。你的任務就是編寫一個程序幫助Tiger來計算這一個值。

第一天的最小波動值爲第一天的營業額。

該天的最小波動值=min{|該天以前某一天的營業額-該天營業額|}。


這道題是比較簡單的, 這次使用了fhq-treap, fhq-treap的優點是好寫.
相對treap, 我覺得找前驅後繼太繁瑣了

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
struct Node{
    Node * left, * right;
    int value, priority;
    Node(){};
    Node(Node * l, Node * r, int v, int p): left(l), right(r), value(v), priority(p){};
};
typedef pair<Node *, Node *> pNN;
Node * null = new Node(), * root = null;
void print(Node * o){
    if(o == null){
        printf(" NULL ");
        return;
    }
    print(o->left);
    printf(" %d ", o->value);
    print(o->right);
}
pNN split_l(Node * o, int val){
    if(o == null){
        return make_pair(null, null);
    }
    pNN result;
    if(o->value <= val){
        result = split_l(o->right, val);
        o->right = result.first;
        result.first = o;
    }
    else{
        result = split_l(o->left, val);
        o->left = result.second;
        result.second = o;
    }
    return result;
}
pNN split_r(Node * o, int val){
    if(o == null){
        return make_pair(null, null);
    }
    pNN result;
    if(o->value < val){
        result = split_r(o->right, val);
        o->right = result.first;
        result.first = o;
    }
    else{
        result = split_r(o->left, val);
        o->left = result.second;
        result.second = o;
    }
    return result;
}
Node * merge(Node * left, Node * right){
    if(left == null){
        return right;
    }
    if(right == null){
        return left;
    }
    if(left->priority < right->priority){
        left->right = merge(left->right, right);
        return left;
    }
    else{
        right->left = merge(left, right->left);
        return right;
    }
}
int getMin(Node * o){
    while(o->left != null){
        o = o->left;
    }
    return o->value;
}
int getMax(Node * o){
    while(o->right != null){
        o = o->right;
    }
    return o->value;
}
void insert(int val){
    pNN first = split_l(root, val);
    pNN second = split_r(first.first, val);
    Node * node = new Node(null, null, val, rand());

    second.second = merge(second.second, node);
    root = merge(merge(second.first, second.second), first.second);
}
int getPre(int val){
    pNN first = split_l(root, val);
    pNN second = split_r(first.first, val);
    if(second.second != null){
        root = merge(merge(second.first, second.second), first.second);
        return second.second->value;
    }
    root = merge(merge(second.first, second.second), first.second);

    pNN tree = split_r(root, val);

    int rst = getMax(tree.first);
    root = merge(tree.first, tree.second);

    return rst;
}
int getNext(int val){
    pNN tree = split_l(root, val);

    int rst = getMin(tree.second);
    root = merge(tree.first, tree.second);

    return rst;
}
int main(){
    null->left = null->right = null;
    // insert(-0x3f3f3f3f), insert(0x3f3f3f3f);
    int n, tmp;
    scanf("%d", &n);
    scanf("%d", &tmp);
    insert(tmp);
    long long sum = tmp;
    print(root);
    printf("sum %lld\n", sum);
    for(int i = 1; i < n; ++i){
        scanf("%d", &tmp);
        sum += min(getNext(tmp) - tmp, tmp - getPre(tmp));
        insert(tmp);
    }
    printf("%lld\n", sum);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章