mxqz CSP-ST4 洛谷民间数据 WA 90pts
  • 板块学术版
  • 楼主LCATreap
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/10/23 17:47
  • 上次更新2023/11/2 11:42:25
查看原帖
mxqz CSP-ST4 洛谷民间数据 WA 90pts
727888
LCATreap楼主2023/10/23 17:47
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int maxn = 4e5 + 10;
struct edge {
	int to, nxt;
}node[maxn]; int head[maxn], n, fa[maxn], cnt = 0;
ll a[maxn], b[maxn], c[maxn];
inline void add(int u, int v) {
	node[cnt].nxt = head[u];
	node[cnt].to = v;
	head[u] = cnt++;
}
void dfs(int u, int f) {
	fa[u] = f;
	for (int i = head[u]; ~i; i = node[i].nxt) {
		int v = node[i].to;
		if (v == f) continue;
		dfs(v, u);
	}
}
ll t[maxn]; int vis[maxn], st[maxn], top = 0;
pair<ll, int>wz[maxn];
inline ll check(ll T) {
	for (int i = 1; i <= n; i++) {
		//bi + x * ci, bi + (x + 1) * ci, ..., bi + T * ci
		//(T - x + 1) * (T - X + 2) / 2 * ci + (T - x + 1) * bi >= ai
		if (b[i] >= a[i]) { t[i] = n; continue; }
		if (b[i] == 0 && c[i] == 0) { t[i] = n - a[i]; continue; }
		auto can = [&](ll x) {
			if (c[i] >= 0) {
				//if (c[i] > 0 && (T + 1) * T / 2 - x * (x - 1) / 2 > (a[i] + c[i] - 1) / c[i]) return true;
				return (__int128_t)((T + 1) * T / 2 - x * (x - 1) / 2) * c[i] + (T - x + 1) * b[i] >= a[i];
			}
			else {
				//bi + u * ci < 1
				//u * ci < 1 - bi
				//u < (1 - bi) / ci
				ll u = (1 - b[i]) / c[i];
				if (b[i] + u * c[i] >= 1) ++u;
				if (T <= u) return (__int128_t)((T + 1) * T / 2 - x * (x - 1) / 2) * c[i] + (T - x + 1) * b[i] >= a[i];
				else return (__int128_t)(u - 1) * u / 2 * c[i] + (u - 1) * b[i] + (T - u + 1) >= a[i];
			}
		};
		ll l = 0, r = n + 1, mid;
		while (l < r) {
			mid = l + r >> 1;
			if (can(mid)) l = mid + 1;
			else r = mid;
		}
		t[i] = l - 1;
	}
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= n; i++) {
		if (t[i] == -1) return 0;
	}
	for (int i = 1; i <= n; i++) wz[i] = { t[i], i };
	sort(wz + 1, wz + n + 1); int p = 0;
	for (int i = 1; i <= n; i++) {
		ll now = wz[i].first; int u = wz[i].second;
		if (now >= n) { vis[u] = -1; continue; } 
		if (vis[u]) continue;
		while (!vis[u] && u) st[++top] = u, u = fa[u];
		for (int j = top; j >= 1; j--) vis[st[j]] = ++p; top = 0;
	}
	for (int i = 1; i <= n; i++) if (vis[i] > t[i]) return 0;
	return 1;
}
int main() {
	memset(head, -1, sizeof(head));
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%lld%lld%lld", &a[i], &b[i], &c[i]);
	for (int i = 1; i < n; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		add(u, v); add(v, u);
	}
	dfs(1, 0);
	ll l = 1, r = 1e9, mid;
	while (l < r) {
		mid = l + r >> 1;
		if (check(mid)) r = mid;
		else l = mid + 1;
	}
	printf("%lld\n", l);
	return 0;
}

大概思路就是二分出 tit_i 表示 ii 最晚种树的时间,排序然后每次跳父结点种树模拟。

2023/10/23 17:47
加载中...