Submission #1193215

#TimeUsernameProblemLanguageResultExecution timeMemory
1193215alexdumitruHarbingers (CEOI09_harbingers)C++20
100 / 100
155 ms29412 KiB
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>

using ll = long long;

const int MAX_N = 100000;
const ll INF = 1e15;

int n;

struct Edge {
    int to, length;
};

std::vector<Edge> g[MAX_N + 1];

struct Harbinger {
    int s, v;
} a[MAX_N + 1];

struct Line {
    ll a, b;
    ll operator() (ll x) {
        return a * x + b;
    }

    Line() : a(0), b(INF) {}
    Line(ll _a, ll _b) : a(_a), b(_b) {}
};

struct Change {
    int node;
    int l;
};

std::stack<Change> changes;

std::vector<int> viteze;

Line lines[MAX_N + 1];

struct LiChaoTree {
    int tree[4 * MAX_N + 1];
    int cnt;

    void add_line(int node, int st, int dr, int l) {
        int mij = (st + dr) / 2;
        if (lines[tree[node]](viteze[mij]) > lines[l](viteze[mij])) {
            changes.push(Change {node, tree[node]});
            std::swap(tree[node], l);
        }
        if (st == dr) return;
        if (lines[l](viteze[st]) < lines[tree[node]](viteze[st]))
            add_line(node * 2, st, mij, l);
        else add_line(node * 2 + 1, mij + 1, dr, l);
    }

    void add_line(Line l) {
        lines[++cnt] = l;
        add_line(1, 0, (int) viteze.size() - 1, cnt);
    }

    ll query(int node, int st, int dr, int pos) {
        ll ans = lines[tree[node]](viteze[pos]);
        if (st == dr)
            return ans;
        int mij = (st + dr) / 2;
        if (pos <= mij)
            ans = std::min(ans, query(node * 2, st, mij, pos));
        else ans = std::min(ans, query(node * 2 + 1, mij + 1, dr, pos));
        return ans;
    }

    ll query(int pos) {
        return query(1, 0, (int) viteze.size() - 1, pos);
    }

    void revert(int snapshot) {
        while ((int) changes.size() > snapshot) {
            Change c = changes.top();
            changes.pop();
            tree[c.node] = c.l;
        }
    }
};

ll sum_path[MAX_N + 1];

LiChaoTree tree;

ll ans[MAX_N + 1];

void dfs(int node, int dad) {
    if (node != 1)
        ans[node] = a[node].s + sum_path[node] * viteze[a[node].v] + tree.query(a[node].v);

    int snapshot = changes.size();

    tree.add_line(Line {-sum_path[node], ans[node]});

    for (auto it : g[node]) {
        if (it.to == dad) continue;

        sum_path[it.to] = sum_path[node] + it.length;

        dfs(it.to, node);
    }

    tree.revert(snapshot);
}

void solve() {
    std::cin >> n;
    for (int i = 1; i < n; i++) {
        int u, v, l;
        std::cin >> u >> v >> l;
        g[u].push_back(Edge {v, l});
        g[v].push_back(Edge {u, l});
    }

    for (int i = 2; i <= n; i++) {
        std::cin >> a[i].s >> a[i].v;
        viteze.push_back(a[i].v);
    }

    std::sort(viteze.begin(), viteze.end());
    viteze.erase(std::unique(viteze.begin(), viteze.end()), viteze.end());

    for (int i = 2; i <= n; i++) {
        a[i].v = std::lower_bound(viteze.begin(), viteze.end(), a[i].v) - viteze.begin();
    }

    dfs(1, 0);

    for (int i = 2; i <= n; i++)
        std::cout << ans[i] << ' ';
}

int main() {
    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...