RT,只有 95 pts,但我拍不出来哪写挂了
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
#include <random>
std::mt19937 rdna(0x383494);
#define UP(i,s,e) for(auto i=s; i!=e; ++i)
using ll = long long;
using i128 = __int128;
using ld = long double;
#define double ld
namespace m{ // }{{{
using std::cin; using std::cout;
decltype(cin) &operator>>(decltype(cin) &in, i128 &x){ long long xx; in >> xx; x = xx; return in; } decltype(cout) &operator<<(decltype(cout) &ou, i128 x){ long long xx = x; ou << xx; return ou; }
constexpr int N = 1e5;
int in;
struct Earth{ ll a, b, c; } eths[N];
std::vector<int> tos[N];
int reach[N], fa[N];
int vis[N];
namespace Fast_Check{/*{{{*/
ll get_grow_len(int pl, ll day){
return eths[pl].b + eths[pl].c * day;
}
void prepare(int pl, int day){
if(eths[pl].c == 0){
reach[pl] = day + 1 - std::ceil(eths[pl].a * 1.0 / eths[pl].b);
return;
}
//double cross = (1-eths[pl].b) / eths[pl].c;
//if(cross == std::ceil(cross)) cross -= 0.5;
//ll upper = std::ceil(cross), downer = std::floor(cross);
//if(eths[pl].c > 0) downer--; else upper++;
//upper++;
if(eths[pl].c < 0){
ll cross = eths[pl].c == 0 ? 0 : (1-eths[pl].b) / (eths[pl].c);
ll upper = cross+1, downer = cross;
if((day+1-upper) >= eths[pl].a){
reach[pl] = day+1-(eths[pl].a);
} else {
double left = day >= upper ?
eths[pl].a - (day+1-upper) :
eths[pl].a + (get_grow_len(pl, day+1) + get_grow_len(pl, downer)) * (double)(downer+1-(day+1)) / 2;
;
double dx = 114514; // (b+c*cross + b+c*cross-dx*c) * (dx+1) / 2 >= a
double aa = -eths[pl].c / 2.0;
double bb = get_grow_len(pl, downer) - eths[pl].c / 2.0;
double cc = get_grow_len(pl, downer) - left;
dx = (-bb + std::sqrt((bb*bb-4*aa*cc))) / (2*aa);
if(std::floor(dx+1e-3) != std::floor(dx-1e-3)) dx = std::round(dx);
reach[pl] = downer - std::ceil(dx);
}
} else {
double aa = -eths[pl].c / 2.0;
double bb = get_grow_len(pl, day) - eths[pl].c / 2.0;
double cc = get_grow_len(pl, day) - eths[pl].a;
double dx = (-bb + std::sqrt((bb*bb-4*aa*cc))) / (2*aa);
if(std::floor(dx+1e-3) != std::floor(dx-1e-3)) dx = std::round(dx);
reach[pl] = std::floor(day - dx);
}
}
}/*}}}*/
namespace Slow_Check{/*{{{*/
double get_grow_len(int pl, double day){
return eths[pl].b + eths[pl].c * day;
}
double get_grow_sum(int pl, int now, int day){
double cross = (1-eths[pl].b) * 1.0 / (eths[pl].c);
if(cross == std::floor(cross)) cross -= 0.5;
if(eths[pl].c < 0){
if(now > cross){
return day + 1 - now; // [now, day+1)
}
return day + 1 - std::ceil(cross)
+ (get_grow_len(pl, now) + get_grow_len(pl, std::floor(cross))) * (std::floor(cross)+1-now) / 2.0;
} else if(eths[pl].c == 0){
return (day+1-now) * 1.0 * eths[pl].b;
} else {
if(now > cross){
return (get_grow_len(pl, now) + get_grow_len(pl, day)) * (day+1-now) / 2.0;
}
return (get_grow_len(pl, std::ceil(cross)) + get_grow_len(pl, day)) * (day+1-std::ceil(cross)) / 2.0
+ std::floor(cross)+1-now;
}
}
void prepare(int pl, int day){
int l = 0, r = day+1; // [l, r)
while(r-l>1){
int mid = (l+r)/2;
if(get_grow_sum(pl, mid, day) >= eths[pl].a){
l = mid;
} else {
r = mid;
}
}
reach[pl] = l;
}
}/*}}}*/
struct Comp_by_reach{ bool operator()(int x, int y) const { return reach[x] < reach[y]; }};
struct Comp_by_far_reach{ bool operator()(int x, int y) const { return reach[x] > reach[y]; }};
std::vector<int> todo;
#if 1
bool check(int maxday){
UP(i, 0, in) Fast_Check::prepare(i, maxday);
//reach[0] = 1;
std::sort(todo.begin(), todo.end(), Comp_by_reach());
std::fill(vis, vis+in, 0);
vis[0] = 0;
int day = 0;
for(int i:todo){
//if(vis[i]) continue;
for(int j=i; !vis[j]; j=fa[j]){
vis[j] = 1;
day++;
}
if(day > reach[i]) return false;
}
return true;
}
#else
std::priority_queue<int, std::vector<int>, Comp_by_reach> pq;
bool check(int maxday){
pq = decltype(pq)();
UP(i, 0, in) prepare(i, maxday);
UP(i, 0, in) if((int)tos[i].size() == 1 && i != 0) pq.push(i);
int day = in;
std::fill(vis, vis+in, 0);
while(!pq.empty()){
int now = pq.top();
pq.pop();
if(reach[now] < day) return false;
vis[fa[now]]++;
if(vis[fa[now]] == (int)tos[fa[now]].size()-1){
pq.push(fa[now]);
}
day--;
}
return true;
}
#endif
void mkfa(int x, int f){
fa[x] = f;
for(int i:tos[x]){
if(i == f) continue;
mkfa(i, x);
}
}
void work(){
cin >> in;
UP(i, 0, in){
cin >> eths[i].a >> eths[i].b >> eths[i].c;
//if(eths[i].c == 0 && eths[i].b < 1) eths[i].b = 1;
}
UP(i, 1, in){
int iu, iv; cin >> iu >> iv; iu--, iv--;
tos[iu].push_back(iv);
tos[iv].push_back(iu);
}
mkfa(0, 0);
todo.reserve(in);
UP(i, 0, in) todo.push_back(i);
int l=in-1, r=1e9;
while(r-l>1){
int mid = (l+r)/2;
if(check(mid)){ r=mid; }
else { l = mid; }
}
cout << r;
}
} // {}}}
signed main(){m::work(); return 0;}