给个小的hack也行
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
struct Node {
long long a;
int b, c, d, cnts, mins;
vector<int> s;
} tr[MAXN];
int n;
inline void mktree(int x, int f) {
tr[x].d = tr[f].d + 1;
tr[x].cnts = 1;
for (auto nx : tr[x].s) {
if (nx != f) {
mktree(nx, x);
tr[x].cnts += tr[nx].cnts;
}
}
}
inline bool check2(int x, register long long l, register long long r) { //第l天到第r天
register long long a = tr[x].a, b = tr[x].b, c = tr[x].c;
register __int128_t _1 = 1;
if (c < 0) {
register long long t = (b - 2 - c) / (-c); //第t天只能+1
register __int128_t xx = r - t + 1;
if (l < t) {
xx += (_1 * (t - 1) - l + 1) * b + ((_1 * (t - 1) * (t - 1) + (t - 1) - l * l + l) >> 1) * c;
}
return xx >= a;
}
return (_1 * r - l + 1) * b + ((_1 * r * r + r - l * l + l) >> 1) * c >= a;
}
int maxl[MAXN];
bool f[MAXN];
inline void getmin(int x, int f) {
tr[x].mins = maxl[x];
for (auto nx : tr[x].s) {
if (nx != f) {
getmin(nx, x);
if (tr[x].mins > tr[nx].mins) tr[x].mins = tr[nx].mins;
}
}
}
struct Node1 {
int i, v;
bool operator < (const Node1& x) const {
return v > x.v;
}
bool operator > (const Node1& x) const {
return v < x.v;
}
};
inline bool check(const int& t) {
// cout << t << ":\n";
for (int i = 1; i <= n; ++i) {
f[i] = 1;
int l = tr[i].d, r = n - tr[i].cnts + 1;
while (l <= r) {
int mid = l + r >> 1;
if (check2(i, mid, t)) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if (r < tr[i].d) return 0;
maxl[i] = r;
// cout << maxl[i] << ' ';
}
// cout << '\n';
getmin(1, 0);
priority_queue<Node1> q;
f[1] = 0;
q.push({1, tr[1].mins});
int nowday = 0;
while (!q.empty()) {
++nowday;
Node1 x = q.top();
// cout << x.i << ' ';
if (nowday > maxl[x.i]) return 0;
q.pop();
for (auto nx : tr[x.i].s) {
if (f[nx]) {
f[nx] = 0;
// cout << nx << "::" << tr[nx].mins << '\n';
q.push({nx, tr[nx].mins});
}
}
}
return 1;
}
int main() {
// freopen("tree4.in", "r", stdin);
// freopen("tree4.out", "w", stdout);
ios_base :: sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> tr[i].a >> tr[i].b >> tr[i].c;
}
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
tr[u].s.push_back(v);
}
tr[0].d = 0;
mktree(1, 0);
// for (int i = 1; i <= n; ++i) {
// // cout << tr[i].d << ' ' << tr[i].cnts << '\n';
// }
int l = n, r = 1e9;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) {
r = mid - 1;
} else {
l = mid + 1;
}
}
cout << l;
return 0;
}