二分答案
再二分出每个点最晚什么时候被选
然后按照最晚被选的时间从前往后贪心
暴力跳即可
复杂度 O ( n log 2 n ) O(n\log^2n) O(nlog2n)
#include<bits/stdc++.h>
using namespace std;
#define int __int128
#define ll long long
//#define int long long
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch>='0' && ch<='9') {
x = (x<<1) + (x<<3) +(ch^48);
ch=getchar();
}
return x * f;
}
void print(int a) {
if(a/10) print(a/10);
putchar(a%10+'0');
}
ll zh(int a) {
if(a/10) return zh(a/10)*10+(ll)(a%10);
return (ll)(a%10);
}
#define pb push_back
#define N 200010
//#define M
//#define mo
struct node {
int a, b, c, id, d;
}a[N];
int ceil(int a, int b) {
return a / b + (a % b ? 1 : 0);
}
int n, m, i, j, k, T, flg, u, v, f[N], w[N], p[N];
vector<int>G[N];
void dfs(int x, int fa) {
f[x] = fa;
for(auto y : G[x])
if(y != fa) dfs(y, x);
}
int S(int l, int r, int n) {
return (l + r) * n / 2;
}
namespace Sol {
int l, r, mid, s, t, i, j, vis[N];
int suan(int i, int l) { //节点i从第r天到第l天
if(l == 0) return a[i].b;
if(a[i].c < 0) {
if(l < p[i]) {
int shou = a[i].b;
int mo = a[i].b + l * a[i].c;
return S(shou, mo, l+1);
}
if(l >= p[i]) return w[i]+(l-p[i]+1);
}
else {
int shou = a[i].b;
int mo = a[i].b + l * a[i].c;
return S(shou, mo, l+1);
}
}
int check(int k) {
// printf("Check : %lld\n", zh(k));
sort(a+1, a+n+1, [] (node x, node y) { return x.id < y.id; });
for(i=1; i<=n; ++i) {
l = 1; r = k;
// if(k==31) printf("%lld %lld\n", zh(suan(i, k)), zh(suan(i, 0)));
if(suan(i, k) - suan(i, 0) < a[i].a) return 0;
while(l < r) {
mid = (l+r+1)>>1;
// printf("%lld [%lld %lld] : %lld %lld %lld\n", i, k, mid, suan(i, k), suan(i, mid-1), suan(i, k) - suan(i, mid-1));
if(suan(i, k) - suan(i, mid-1) >= a[i].a) l=mid;
else r=mid-1;
}
a[i].d=l; //最晚在第d天点亮
printf("last %lld : %lld\n", zh(i), zh(a[i].d));
}
sort(a+1, a+n+1, [] (node x, node y) { return x.d < y.d; });
memset(vis, 0, sizeof(vis));
vis[1] = j = 1;
for(i=1; i<=n; ++i) {
int x = a[i].id;
if(!vis[x]) {
int y = x;
while(!vis[y]) y = f[y], ++j;
vis[x] = j; y = x;
while(!vis[f[y]]) vis[f[y]]=vis[y]-1, y=f[y];
}
// printf("vis[%lld] = %lld\n", zh(x), zh(vis[x]));
if(vis[x] > a[i].d) return 0;
}
// printf("OK ! \n");
return 1;
}
}
signed main() {
// freopen("tree.in", "r", stdin);
// freopen("tree.out", "w", stdout);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// srand(time(0));
// T=read();
// while(T--) {
// }
n=read();
for(i=1; i<=n; ++i) {
a[i].id=i;
a[i].a=read(); a[i].b=read(); a[i].c=read();
}
for(i=1; i<n; ++i) {
u=read(); v=read();
G[u].pb(v); G[v].pb(u);
}
dfs(1, 0);
int l, r, mid;
for(i=1; i<=n; ++i)
if(a[i].c < 0) {
l = a[i].b / (-a[i].c) ;
for(j = l-3; j <= l+3; ++j)
if(a[i].b + j *a[i].c < 1) break;
p[i] = j ; // 从第p[i]天开始出事
int shou = a[i].b, mo = a[i].b + (j-1)*a[i].c;
w[i] = S(shou, mo, j);
// printf("%lld : %lld | %lld\n", zh(i), zh(p[i]), zh(w[i])) ;
}
l=n; r=1e9;
while(l < r) {
mid = (l + r) >> 1;
if(Sol::check(mid)) r = mid;
else l = mid + 1;
}
print(l);
// printf("%lld", l);
return 0;
}