之前的帖子说是二分写挂了,但是我真的调不出来。
数据点 15 与答案相差 1。
代码写了注释的。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define ll __int128_t
const int maxn = 2e5 + 5;
const int maxday = 1e9 + 5;
template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();} x *= f;
}
template <typename T,typename... Args>
inline void read(T &x,Args&... Arg){read(x),read(Arg...);}
int n;
ll a[maxn],b[maxn],c[maxn];
int head[maxn],cnt;
struct Edge{
int to,next;
}e[maxn << 1];
inline void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
ll one[maxn]; //one[i]:第i块地最早第多少天开始只会增高1m
inline ll Ceil(ll x,ll y){
if(x % y == 0) return x / y;
return x / y + 1;
}
inline void init(){ //预处理one
for(int i=1;i<=n;i++){
if(c[i] > 0) one[i] = -2;
else if(c[i] == 0) one[i] = -3; //两种特殊情况打上不同的标记
else one[i] = Ceil(b[i] - 1,-c[i]);
}
}
ll deadline[maxn]; //deadline[i]:第i块地最晚只能在第多少天种下才行
inline void dfs(int u,int fa){
for(int i=head[u];i;i=e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs(v,u);
deadline[u] = min(deadline[u],deadline[v] - 1);
}
}
inline bool check(int day){ //分类讨论即可
for(int i=1;i<=n;i++){
if(one[i] == -3){
deadline[i] = day + 1 - Ceil(a[i],b[i]);
if(deadline[i] <= 0) return 0;
}
else if(one[i] == -2){
ll l = 1,r = day,mid;
deadline[i] = 0;
while(l <= r){
mid = (l + r) >> 1;
ll num = ((mid + day) * (day - mid + 1) / 2) * c[i] + (day - mid + 1) * b[i];
if(num >= a[i]) deadline[i] = mid,l = mid + 1;
else r = mid - 1;
}
if(!deadline[i]) return 0;
}
else{
if(day - one[i] + 1 >= a[i]) deadline[i] = day + 1 - a[i];
else{
ll need = a[i] - (day - one[i] + 1);
deadline[i] = 0;
ll l = 1,r = one[i] - 1,mid;
while(l <= r){
mid = (l + r) >> 1;
ll num = ((mid + one[i] - 1) * (one[i] - mid) / 2) * c[i] + (one[i] - mid) * b[i];
if(num >= need) deadline[i] = mid,l = mid + 1;
else r = mid - 1;
}
if(!deadline[i]) return 0;
}
}
}
dfs(1,1);
sort(deadline + 1,deadline + 1 + n); //按顺序填充
for(int i=1;i<=n;i++) if(i > deadline[i]) return 0;
return 1;
}
int main(){
//freopen("tree15.in","r",stdin);
read(n);
for(int i=1;i<=n;i++) read(a[i],b[i],c[i]);
for(int i=1;i<n;i++){
int u,v;
read(u,v);
add(u,v);
add(v,u);
}
init();
int l = n,r = maxday,mid; //二分答案
int ans = 0;
while(l <= r){
mid = (l + r) >> 1;
if(check(mid)) r = mid - 1,ans = mid;
else l = mid + 1;
}
printf("%d\n",ans);
return 0;
}