CF505E Mr. Kitayuta vs. Bamboos

题目链接

最小化最大值就是二分答案,我们现在二分最后最大值为 \(H\),希望知道能否让最终的值都不超过 \(H\)

发现正着做很不可做,考虑时光倒流:

一开始所有的竹子都是 \(H\) 这么高,每天会自己降低 \(a_i\),然后我们有权用 \(k\) 次“拔高”的机会,每次可以拔高 \(p\)。要求:每时每刻都不能存在一个竹子的高度为负数(不可能有从负数长出来的情况);最终每个竹子的高度都 \(\ge h_i\)(真实情况下如果低一些顶多就是某一天砍到 0 就不砍到负数了,但是如果高一些的话最终就达不到 \(H\) 了)

这两个要求中,第一个要求最为紧急,必须在“死期”之前赶紧拔高;第二个要求就什么时候拔都行了,随便找一个拔即可。由于如果现在啥也不拔就能够保证符合第二个要求的话,第一个要求就肯定不成问题了,或者说在不拔的情况下不符合第一个要求就一定不符合第二个要求,因此我们可以直接拔最快到“死期”的那个竹子,这是最优决策。

相关参数:死期 \(= \left \lfloor \frac{H}{a_i} \right \rfloor + 1\)

关键代码:

inline bool che(ll H) {
	while (!q.empty())	q.pop();
	for (int i = 1; i <= n; ++i)	nw[i] = H;
	for (int i = 1; i <= n; ++i)
		if (H - 1ll * m * a[i] < h[i])	q.push(MP(-(H/a[i]),i));
	for (int i = 1; i <= m; ++i) {
		for (int j = 1; j <= k; ++j) {
			if (q.empty())	return true;
			PLL pr = q.top(); q.pop();
			if (-pr.first < i)	return false;
			int id = pr.second;
			nw[id] += p;
			if (nw[id] - 1ll * m * a[id] < h[id])	q.push(MP(-(nw[id]/a[id]),id));
		}
	}
	return q.empty();
}
posted @ 2020-09-17 16:54  JiaZP  阅读(189)  评论(0编辑  收藏  举报