Submission #1265831

#TimeUsernameProblemLanguageResultExecution timeMemory
1265831nanaseyuzukiHarbingers (CEOI09_harbingers)C++20
60 / 100
116 ms46708 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const ll INFLL = LLONG_MAX;

struct Line { ll m, b; // y = m*x + b
};

struct Change { int idx; Line prev; };

struct LiChao {
    int n;
    vector<ll> xs;
    vector<Line> seg;
    vector<Change> changes;

    LiChao(const vector<ll>& _xs) {
        xs = _xs;
        n = xs.size();
        seg.assign(4*n, {0, (ll)9e18});
    }

    inline ll eval(const Line &ln, ll x) {
        return ln.m * x + ln.b;
    }

    void add_line(Line ln, int id=1, int l=0, int r=-1) {
        if (r==-1) r = n-1;
        int m = (l+r)>>1;
        ll xl = xs[l], xm = xs[m], xr = xs[r];
        Line cur = seg[id];
        // record change
        changes.push_back({id, cur});
        // at mid, which line is better?
        if (eval(ln, xm) < eval(cur, xm)) swap(ln, seg[id]);
        // now seg[id] is better at xm
        if (l==r) return;
        if (eval(ln, xl) < eval(seg[id], xl)) {
            // new line better on left
            add_line(ln, id<<1, l, m);
        } else if (eval(ln, xr) < eval(seg[id], xr)) {
            // new line better on right
            add_line(ln, id<<1|1, m+1, r);
        }
    }

    ll query(ll xq, int id=1, int l=0, int r=-1) {
        if (r==-1) r = n-1;
        int m = (l+r)>>1;
        ll res = eval(seg[id], xq);
        if (l==r) return res;
        if (xq <= xs[m]) return min(res, query(xq, id<<1, l, m));
        else           return min(res, query(xq, id<<1|1, m+1, r));
    }

    int snapshot() { return changes.size(); }
    void rollback(int snap) {
        while ((int)changes.size() > snap) {
            auto ch = changes.back(); changes.pop_back();
            seg[ch.idx] = ch.prev;
        }
    }
};

const int MN = 100000 + 5;
int n;
vector<pair<int,ll>> adj[MN];
ll s[MN], v[MN];
ll dp[MN], distd[MN];

vector<ll> allX;

void dfs(int u, int p, LiChao &cht) {
    int snap = cht.snapshot();
    // add line for u
    cht.add_line({-distd[u], dp[u]});
    for (auto &ed : adj[u]) {
        int w = ed.first;
        ll c = ed.second;
        if (w == p) continue;
        distd[w] = distd[u] + c;
        // query cht at x = v[w]
        ll best = cht.query(v[w]);
        dp[w] = best + v[w] * distd[w] + s[w];
        dfs(w, u, cht);
    }
    cht.rollback(snap);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n;
    for (int i = 1; i < n; i++) {
        int u, w; ll c;
        cin >> u >> w >> c;
        adj[u].push_back({w, c});
        adj[w].push_back({u, c});
    }
    for (int i = 2; i <= n; i++) {
        cin >> s[i] >> v[i];
        allX.push_back(v[i]);
    }
    // include root's v if needed
    allX.push_back(0);
    sort(allX.begin(), allX.end());
    allX.erase(unique(allX.begin(), allX.end()), allX.end());

    LiChao cht(allX);
    // initialize root dp and dist
    dp[1] = 0;
    distd[1] = 0;
    // add base line y = 0*x + 0
    cht.add_line({0, 0});

    dfs(1, 0, cht);

    for (int i = 2; i <= n; i++) cout << dp[i] << " ";
    cout << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...