#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>
using namespace std;
// BEGIN NO SAD
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef vector<int> vi;
// END NO SAD
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<ll>> matrix;
typedef pair<ll, ll> pll;
struct Line {
mutable ll k, m, p;
bool operator<(const Line& o) const { return k < o.k; }
bool operator<(ll x) const { return p < x; }
};
struct LineContainer : multiset<Line, less<>> {
// (for doubles, use inf = 1/.0, div(a,b) = a/b)
const ll inf = 1LL << 62;
ll div(ll a, ll b) { // floored division
return a / b - ((a ^ b) < 0 && a % b); }
bool isect(iterator x, iterator y) {
if (y == end()) { x->p = inf; return false; }
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
else x->p = div(y->m - x->m, x->k - y->k);
return x->p >= y->p;
}
void add(ll k, ll m) {
k *= -1;
m *= -1;
auto z = insert({k, m, 0}), y = z++, x = y;
while (isect(y, z)) z = erase(z);
if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
while ((y = x) != begin() && (--x)->p >= y->p)
isect(x, erase(y));
}
ll query(ll x) {
assert(!empty());
auto l = *lower_bound(x);
ll val = -(l.k * x + l.m);
return val;
}
};
int n;
vector<pii> edges[100005];
ll ret[100005];
ll dist[100005];
ll gain[100005];
ll timeper[100005];
LineContainer lc;
void dfs(int curr, int par) {
if(curr > 1) {
ret[curr] = gain[curr] + timeper[curr]*dist[curr] + lc.query(timeper[curr]);
}
for(pii out: edges[curr]) {
if(out.first == par) continue;
lc.add(-dist[curr], ret[curr]);
dist[out.first] = dist[curr] + out.second;
dfs(out.first, curr);
Line l;
l.k = dist[curr];
l.m = -ret[curr];
l.p = -(1LL << 62);
auto it = lc.lower_bound(l);
if(it == lc.end()) {
continue;
}
Line q = *it;
if(l.k != q.k) {
continue;
}
if(l.m != q.m) {
continue;
}
lc.erase(it);
}
}
void solve() {
cin >> n;
for(int i = 1; i < n; i++) {
int a, b, w;
cin >> a >> b >> w;
edges[a].emplace_back(b, w);
edges[b].emplace_back(a, w);
}
for(int i = 2; i <= n; i++) cin >> gain[i] >> timeper[i];
dfs(1, -1);
for(int i = 2; i <= n; i++) cout << ret[i] << " \n"[i == n];
}
// are there edge cases (N=1?)
// are array sizes proper (scaled by proper constant, for example 2* for koosaga tree)
// integer overflow?
// DS reset properly between test cases
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
solve();
}
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
7 ms |
2688 KB |
Output isn't correct |
2 |
Correct |
8 ms |
3200 KB |
Output is correct |
3 |
Correct |
58 ms |
11988 KB |
Output is correct |
4 |
Correct |
82 ms |
16504 KB |
Output is correct |
5 |
Correct |
102 ms |
19484 KB |
Output is correct |
6 |
Correct |
135 ms |
23288 KB |
Output is correct |
7 |
Incorrect |
74 ms |
12664 KB |
Output isn't correct |
8 |
Incorrect |
133 ms |
19964 KB |
Output isn't correct |
9 |
Incorrect |
129 ms |
20344 KB |
Output isn't correct |
10 |
Incorrect |
128 ms |
21148 KB |
Output isn't correct |