P9755 [CSP-S 2023] 种树 题解

二分答案(最少天数)。

下面是判断一个天数是否满足条件:

对每个点二分出最晚的种树时间。

\(\tt Dfs\) 一遍:对于每个点,遍历完子树后将其的最晚种树时间与 \(\text{儿子的最晚种树时间}-1\) 取最小值,得到的就是真实的最晚种树时间。

最后只要对于每个 \(i(1\le i\le n)\),最晚种树时间不超过 \(i\) 的点的个数 \(\le i\) 就可以了,做一遍前缀和即可。注意,取最小值以后最晚种树时间可能 \(\le0\),要特判。求一段时间内的生长高度时需要用 __int128,会爆 long long

时间复杂度 \(O(n\log V\log n)\),常数很小。

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mxn 100003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
int n,p[mxn],d[mxn],ct[mxn];
ll a[mxn],b[mxn],c[mxn];
vector<int>g[mxn];
bool v[mxn];
inline __int128 get(ll i,ll n,__int128 a,__int128 b){
    if(a<0){
        ll d=min((b-a-1)/(-a),(__int128)n+1);
        if(d<=i)return n-i+1;
        return n-d+1+(d-i)*b+(d-1+i)*(d-i)/2*a;
    }
    return (n+i)*(n-i+1)/2*a+b*(n-i+1);
}
void dfs(int x,int fa){
	for(int i:g[x])if(i!=fa){
		dfs(i,x);
		p[x]=min(p[x],p[i]-1);
	}
} 
bool check(int mx){
    rep(i,1,n){
        if(a[i]>get(1,mx,c[i],b[i]))return 0;
        int l=1,r=n;
        while(l<r){
            int mid=(l+r+1)>>1;
            if(a[i]<=get(mid,mx,c[i],b[i]))l=mid;
            else r=mid-1;
        }
        if(i==1)l=1;
        p[i]=l;
    }
    dfs(1,0);
    rep(i,1,n)ct[i]=0;
    rep(i,1,n){
    	if(p[i]<1)return 0;
    	ct[p[i]]++;
	}
	rep(i,1,n){
		ct[i]+=ct[i-1];
		if(ct[i]>i)return 0;
	}
    return 1;
}
signed main(){
    scanf("%d",&n);
    rep(i,1,n)scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
    for(int i=1,x,y;i<n;++i){
        scanf("%d%d",&x,&y);
        g[x].pb(y),g[y].pb(x);
    }
    int l=n,r=1e9;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    cout<<l;
    return 0;
}
posted @   zifanwang  阅读(54)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示