函数分工很清晰。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[100009];
int b[100009];
int c[100009];
struct st{
int v,ne;
}sd[200009];
int h[100009];
int inn;
int n;
void add(int u,int v){
sd[++inn].v=v;
sd[inn].ne=h[u];
h[u]=inn;
}
int fa[100009];
bool vis[100009];
pair<int,int> g[100009];
inline __int128 mm(int t,int r){//计算第 t 棵树如果第一天就种下,r 天长多高
if(r<=0){
return 0;
}
int x;
if(c[t]<0)
x=ceil((1-b[t])*1.0/c[t]);
else{
x=1e16;
}
x=max(x,1ll);
__int128 ans;
ans=0;
if(x<=r){
ans+=r-x+1;
r=x-1;
}
ans+=(__int128)r*b[t];
ans+=(__int128)r*(__int128)(r+1)/2*(__int128)c[t];
return ans;//死亡不等式计算
}
inline int fd(int t,int y){
int l,r;
l=0,r=y;
while(l<r){
int mid;
mid=l+r+1;
mid>>=1;
if((__int128)(mm(t,y)-mm(t,mid-1))>=(__int128)a[t]){//区间长高是否达到要求
l=mid;
}else{
r=mid-1;
}
}
return r;
}
inline void dfs(int t,int fat){
fa[t]=fat;
for(int i=h[t];i;i=sd[i].ne){
if(sd[i].v!=fat){
dfs(sd[i].v,t);
}
}
}
inline void input(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i]>>c[i];
}
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,0);
}
inline bool check(int x){
for(int i=1;i<=n;i++){
vis[i]=0;
g[i].second=i;
g[i].first=fd(i,x);
if(g[i].first<=0){
return 0;
}
}
sort(g+1,g+1+n);
int dy;
dy=0;
for(int i=1;i<=n;i++){
int t;
t=g[i].second;
while(!vis[t]&&t){
vis[t]=1;
dy++;
t=fa[t];
}
if(dy>g[i].first){
return 0;
}
}
return 1;
}
inline int reply(){
int l,r;
l=1,r=(1ll<<25);
while(l<r){
int mid;
mid=l+r;
mid>>=1;
if(check(mid)){
r=mid;
}else{
l=mid+1;
}
}
return l;
}
signed main(){
std::ios::sync_with_stdio(0);
input();
cout<<reply();
return 0;
}