CSP-S T4 90分二分贪心求调,有可能假了
查看原帖
CSP-S T4 90分二分贪心求调,有可能假了
378706
MoyunAllgorithm楼主2023/10/23 18:48

思路:二分出结束天数 midmid,对其 check,得到对于 ii 点的最晚合法时间,之后在树上递推向上

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN=1e5+5;
LL a[MAXN];
int b[MAXN],c[MAXN];
vector<int>gra[MAXN];
int lim[MAXN],dp[MAXN];
int N;
bool Chk(int i,int day,int x)
{
//	printf("Chk%d %d %d ",i,day,x);
	int d=day-x+1;
	__int128 h=(__int128) b[i]*d+(__int128)(x+day)*(day-x+1)/2*c[i];
	if(c[i]<0) 
	{
		int m=(floor)((double)b[i]-1)/(-c[i]);
	//	printf("[%d %lld %d]\n",m,b[i],-c[i]);
		h=(__int128) b[i]*(m-x+1)+(__int128)(x+m)*(m-x+1)/2*c[i];
		h+=(__int128) day-m;
		if(m==0) h=d;
	}
	//printf("%lld %lld\n",(LL)h,a[i]);
	h=max(h,(__int128)d);
	if(h>=(__int128) a[i]) return true;
	return false;
}
void dpfs(int u,int fa)
{
	dp[u]=lim[u];
	for(int i=0;i<gra[u].size();i++)
	{
		int v=gra[u][i];
		if(v==fa) continue;
		dpfs(v,u);
		dp[u]=min(dp[u],dp[v]-1);
	}
	return;
}
bool Check(int x)
{
	//printf("Check%d\n",x);
	for(int i=1;i<=N;i++)
	{
		int l=1,r=x,res=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(Chk(i,x,mid)) res=mid,l=mid+1;
			else r=mid-1;
		}
		if(!res) return false;
		lim[i]=res;
	}
//	for(int i=1;i<=N;i++) printf("%d ",lim[i]);
	dpfs(1,0);
	sort(dp+1,dp+N+1);
	if(dp[1]<1) return false;
	for(int i=1;i<=N;i++)
	{
		if(dp[i]<i) return false;
	}
//	puts("OK!!");
	return true;
}
int main()
{
	scanf("%d",&N);
	for(int i=1;i<=N;i++) scanf("%lld %d %d",&a[i],&b[i],&c[i]);
	for(int i=1;i<N;i++)
	{
		int u,v;
		scanf("%d %d",&u,&v);
		gra[u].push_back(v);
		gra[v].push_back(u);
	}
//	Chk(1,100,50);
//	return 0;
	int l=0,r=1e9,ans;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(Check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d\n",ans);
    return 0;
}
2023/10/23 18:48
加载中...