제출 #965357

#제출 시각아이디문제언어결과실행 시간메모리
965357MisterReaperHarbingers (CEOI09_harbingers)C++17
0 / 100
78 ms25524 KiB
#include <bits/stdc++.h> using i64 = long long; constexpr int maxN = 1E5 + 5; constexpr i64 INF = 1E18; int N; std::vector<std::pair<int, int>> adj[maxN]; int S[maxN], V[maxN], par[maxN], D[maxN]; i64 dp[maxN]; struct line { i64 a, b; line(i64 _a, i64 _b) : a(_a), b(_b) {} i64 eval(i64 x) { return 1LL * a * x + b; } long double intersect(line rhs) { assert(a != rhs.a); return (b - rhs.b) / (rhs.a - a); } }; std::ostream& operator<< (std::ostream& os, line l) { return os << '(' << l.a << "x + " << l.b << ')'; } struct CHTrick { std::deque<int> before; std::deque<line> dq; std::deque<line> rem; CHTrick() {} int size() { return (int) dq.size(); } i64 query(i64 x) { int l = 0, r = size() - 1; while(r - l > 3) { int m = (l + r) >> 1; if(dq[m].eval(x) <= dq[m + 1].eval(x)) { l = m; } else { r = m; } } i64 res = INF; for(int i = l; i <= r; i++) { res = std::min(res, dq[i].eval(x)); } return res; } void add(line l) { before.emplace_back(size()); while(size() >= 2 && l.intersect(dq[0]) <= dq[0].intersect(dq[1])) { rem.push_back(dq[0]); dq.pop_front(); } dq.push_front(l); } void rollback() { dq.pop_front(); std::deque<line> save; while((int) save.size() + size() != before.back()) { save.push_front(rem.back()); rem.pop_front(); } while(!save.empty()) { dq.push_front(save.back()); save.pop_back(); } before.pop_back(); } } CHT; std::ostream& operator<< (std::ostream& os, CHTrick w) { os << '{'; for(int i = 0; i < w.size(); i++) { if(i != 0) { os << ", "; } os << w.dq[i]; } return os << '}'; } void dfs(int v) { // std::cerr << "vertex: " << v << '\n'; if(v != 1) { dp[v] = CHT.query(V[v]) + 1LL * D[v] * V[v] + S[v]; } CHT.add({-D[v], dp[v]}); // std::cerr << CHT << '\n'; for(auto [u, w] : adj[v]) { if(u == par[v]) { continue; } D[u] = D[v] + w; par[u] = v; dfs(u); } // std::cerr << "roll\n"; CHT.rollback(); // std::cerr << CHT << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cin >> N; for(int i = 1; i <= N - 1; i++) { int A, B, W; std::cin >> A >> B >> W; adj[A].emplace_back(B, W); adj[B].emplace_back(A, W); } for(int i = 2; i <= N; i++) { std::cin >> S[i] >> V[i]; } std::fill_n(&dp[1], N, INF); dp[1] = 0; par[1] = 1; dfs(1); for(int i = 2; i <= N; i++) { std::cout << dp[i] << " \n"[i == N]; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...