제출 #373724

#제출 시각아이디문제언어결과실행 시간메모리
373724KoDFireworks (APIO16_fireworks)C++17
100 / 100
1128 ms94760 KiB
#include <bits/stdc++.h>

template <class T>
using Vec = std::vector<T>;
using ll = long long;

template <class F>
struct RecLambda: private F {
    explicit RecLambda(F &&f): F(std::forward<F>(f)) { }
    template <class... Args>
    decltype(auto) operator () (Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);        
    }
};

struct HeapNode;
using Heap = std::unique_ptr<HeapNode>;

struct HeapNode {
    ll value;
    Heap left, right;
    HeapNode(const ll value): value(value), left(), right() { }
};

Heap merge(Heap left, Heap right) {
    if (!left) return right;
    if (!right) return left;
    if (left -> value < right -> value) {
        std::swap(left, right);
    }
    left -> right = merge(std::move(left -> right), std::move(right));
    std::swap(left -> left, left -> right);
    return left;
}

void push(Heap &heap, const ll value) {
    heap = merge(std::move(heap), std::make_unique<HeapNode>(value));
}

ll top(Heap &heap) {
    return heap -> value;
}

ll pop(Heap &heap) {
    const auto ret = top(heap);
    heap = merge(std::move(heap -> left), std::move(heap -> right));
    return ret;
}

struct SlopeTrick {
    ll last_slope, last_y;
    Heap changes;

    SlopeTrick(): last_slope(), last_y(), changes() { 
        push(changes, 0);
    }
    
    void absorb(SlopeTrick &&other) {
        const auto x1 = top(changes);
        const auto x2 = top(other.changes);
        last_y += other.last_y + (x1 < x2 ? last_slope * (x2 - x1) : other.last_slope * (x1 - x2));
        last_slope += other.last_slope;
        changes = merge(std::move(changes), std::move(other.changes));
    }

    bool pop_last() {
        const auto x1 = pop(changes);
        if (!changes) return false;
        const auto x2 = top(changes);
        last_slope -= 1;
        last_y += last_slope * (x2 - x1);
        return true;
    }
};

int main() {
    int N, M;
    std::cin >> N >> M;
    Vec<Vec<std::pair<int, int>>> children(N + M);
    for (int i = 1; i < N + M; ++i) {
        int p, c;
        std::cin >> p >> c;
        p -= 1;
        children[p].emplace_back(i, c);
    }
    Vec<SlopeTrick> data(N);
    RecLambda([&](auto dfs, const int u) -> void {
        for (const auto [v, c]: children[u]) {
            if (v >= N) {
                SlopeTrick trick;
                trick.last_slope = 1;
                push(trick.changes, c);
                push(trick.changes, c);
                data[u].absorb(std::move(trick));
            }
            else {
                dfs(v);
                while (data[v].last_slope > 1) {
                    data[v].pop_last();
                }
                const auto x1 = pop(data[v].changes);
                const auto x2 = pop(data[v].changes);
                push(data[v].changes, x2 + c);
                push(data[v].changes, x1 + c);
                data[u].absorb(std::move(data[v]));
            }
        }
    })(0);
    ll ans = data[0].last_y;
    while (data[0].pop_last()) {
        ans = std::min(ans, data[0].last_y);
    }
    std::cout << ans << '\n';
    return 0;    
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...