Submission #1214032

#TimeUsernameProblemLanguageResultExecution timeMemory
1214032trinm01Harbingers (CEOI09_harbingers)C++20
70 / 100
1096 ms13636 KiB
#include <bits/stdc++.h> using namespace std; #define int long long const int MAXN = 100000 + 5; const int MAXE = 200000 + 5; const int INF = 1e18; int n; int s[MAXN], p[MAXN], d[MAXN], f[MAXN]; // Adjacency as static edge list int head[MAXN], to[MAXE], cost[MAXE], nxt[MAXE], ecnt; // A, B arrays for CHT int Aarr[MAXN], Barr[MAXN], asz = 0; // Pop‐stack arrays int popAarr[MAXN], popBarr[MAXN], popSz = 0; // Number of pops performed when adding at node u int popRange[MAXN]; void addEdge(int u, int v, int c) { nxt[ecnt] = head[u]; to[ecnt] = v; cost[ecnt] = c; head[u] = ecnt++; } bool bad(int l1, int l2, int l3) { // compare (B[l3]-B[l1])*(A[l1]-A[l2]) < (B[l2]-B[l1])*(A[l1]-A[l3]) long double lhs = (long double)(Barr[l3] - Barr[l1]) * (Aarr[l1] - Aarr[l2]); long double rhs = (long double)(Barr[l2] - Barr[l1]) * (Aarr[l1] - Aarr[l3]); return lhs < rhs; } void addLine(int a, int b, int u) { popRange[u] = 0; Aarr[asz] = a; Barr[asz] = b; asz++; while (asz >= 3 && bad(asz - 3, asz - 2, asz - 1)) { // pop the middle line int idx = asz - 2; popAarr[popSz] = Aarr[idx]; popBarr[popSz] = Barr[idx]; popSz++; // remove it: shift elements left at idx for (int i = idx; i + 1 < asz; i++) { Aarr[i] = Aarr[i + 1]; Barr[i] = Barr[i + 1]; } asz--; popRange[u]++; } } void rollback(int u) { // remove the line added for u asz--; // restore popped lines in reverse order for (int i = 0; i < popRange[u]; i++) { popSz--; // append restored line to end Aarr[asz] = popAarr[popSz]; Barr[asz] = popBarr[popSz]; asz++; } } int queryCHT(int x) { if (asz == 0) return 0; if (asz == 1) return Aarr[0] * x + Barr[0]; int l = 1, r = asz - 1, id = 1; int ans = INF; while (l <= r) { int mid = (l + r) >> 1; int y1 = Aarr[mid] * x + Barr[mid]; int y2 = Aarr[mid - 1] * x + Barr[mid - 1]; if (y1 < y2) { id = mid; ans = min(ans, y1); l = mid + 1; } else { ans = min(ans, y2); r = mid - 1; } } ans = min(ans, Aarr[id] * x + Barr[id]); if (id - 1 >= 0) ans = min(ans, Aarr[id - 1] * x + Barr[id - 1]); if (id + 1 < asz) ans = min(ans, Aarr[id + 1] * x + Barr[id + 1]); return ans; } void dfs_iterative() { struct Item { int u, par, state; }; vector<Item> st; st.reserve(n * 2); d[1] = 0; st.push_back({1, 0, 0}); while (!st.empty()) { Item it = st.back(); st.pop_back(); int u = it.u, par = it.par, state = it.state; if (state == 0) { if (u != 1) { int best = queryCHT(p[u]); f[u] = best + d[u] * p[u] + s[u]; } else { f[u] = 0; } addLine(-d[u], f[u], u); st.push_back({u, par, 1}); for (int e = head[u]; e != -1; e = nxt[e]) { int v = to[e], c = cost[e]; if (v == par) continue; d[v] = d[u] + c; st.push_back({v, u, 0}); } } else { rollback(u); } } } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; for (int i = 1; i <= n; i++) { head[i] = -1; } ecnt = 0; for (int i = 1; i < n; i++) { int u, v, c; cin >> u >> v >> c; addEdge(u, v, c); addEdge(v, u, c); } for (int i = 2; i <= n; i++) { cin >> s[i] >> p[i]; } asz = 0; popSz = 0; dfs_iterative(); for (int i = 2; i <= n; i++) { cout << f[i] << ' '; } cout << "\n"; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...