ans

㊗️:☀️☃️☃️☃️☀️  •  1个月前


#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int n;
struct grow
{
	long long a;
	int b, c;
	int bp; //max(b+cx,1)两者的相交点
	void make() {
		if (c == 0) {
			b = max(b, 1);  
		}
		else { 
			bp = (1 - b) / c;
			if (c > 0 && (1 - b) % c ) bp++;
		} 
	}
	bool check(int startDay, int endDay) {
		long long high = a;
		if (c >= 0) {
			if (startDay < bp && endDay < bp) return endDay - startDay + 1 >= high;
			if (startDay < bp) {
				high -= bp - startDay;
				startDay = bp;
			}
			return (1ll * c * startDay + b + 1ll * c * endDay + b) >= (long double)high / (endDay - startDay + 1) * 2;
		}
		else {
			if (endDay > bp && startDay > bp) return endDay - startDay + 1 >= high;
			else if (endDay > bp) {
				high -= endDay - bp;
				endDay = bp;
			}
			return (1ll * c * startDay + b + 1ll * c * endDay + b) >= (long double)high / (endDay - startDay + 1) * 2;
		}
	}
}gl[100001];
struct info {
	int index;
	int day;
	bool operator <(info i2) {
		return day < i2.day;
	}
}list[100001];
bool planed[100001]; //某个点是否已安排
int fa[100001];
bool check(int endday) {
	//倒推算出各个点至少开始种的时间
	for (int i = 1; i <= n; i++) {
		int left = 0, right = endday;
		while (left < right) { //二分查找种的第一天
			int mid = (left + right) / 2 + 1;	
			if (gl[i].check(mid, endday)) left = mid;
			else right = mid - 1;
		}
		if (left == 0) return false;
		list[i].index = i;
		list[i].day = left;
	}
	sort(list + 1, list + n + 1);
	memset(planed, 0, sizeof planed);
	int planday = 0;//已安排天数
	for (int i = 1; i <= n; i++) {
		int node = list[i].index;
		while (!planed[node] && node)
		{
			planday++;
			planed[node] = true;
			node = fa[node];
		}
		if (planday > list[i].day) return false;
	}
	return true;
}
vector<int> map[100001];
void dfs(int node) {
	for (int next : map[node]) if (next != fa[node]) {
		fa[next] = node;
		dfs(next);
	}
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> gl[i].a >> gl[i].b >> gl[i].c;
		gl[i].make();
	}
	for (int i = 0; i < n - 1; i++) {
		int a, b;
		cin >> a >> b;
		map[a].push_back(b);
		map[b].push_back(a);
	}
	dfs(1);
	int left = 1, right = 1e9;
	while (left < right) {
		int mid = (left + right) / 2;
		if (check(mid)) right = mid;   //检查mid天能否完成任务 
		else left = mid + 1;
	}
	cout << left;
	return 0;
}

评论:

请先登录,才能进行评论