CF505E Mr. Kitayuta vs. Bamboos 题解
题意
- 给定 个数 。
- 你需要进行 轮操作,每轮操作为 次修改,每次修改可以选择一个数 修改为 。
- 每轮操作后每个 将会被修改为 。
- 你需要最小化最终 中的最大值。
- ,,。
题解
首先二分答案。
判定的时候,发现正着判很麻烦,考虑倒序。
那么就相当于,每轮操作为:
- 将每个 修改为 ,这里需要保证 。
- 次修改,每次修改可以选择一个数 修改为 。
- 要求最终的 均不小于给定的 个数。
那么可以考虑贪心:
- 每次选择最容易导致 的位置加上 ,如果选完了还是会导致则判定不合法。
- 如果不存在可能导致 的位置,则直接判定剩下的次数是否足够使最终的 均不小于给定的 个数。
时间复杂度 。
代码
const int N = 1e5 + 7;
int n, m, k, c[N];
ll h[N], a[N], p, l, r;
inline bool pd(ll o) {
pq< pi > q;
for (int i = 1; i <= n; i++) {
if (h[i] + m * a[i] <= o) continue;
q.push(mp(-(o / a[i]), i)), c[i] = 0;
}
int cnt = 0;
for (int i = 1; q.size() && i <= m; i++)
for (int j = 1; q.size() && j <= k; j++) {
if (-q.top().fi < i) return 0;
int x = q.top().se;
q.pop();
ll w = (o + (++c[x]) * p) / a[x];
if (w < m) q.push(mp(-w, x));
++cnt;
}
for (int i = 1; i <= n; i++) {
ll w = o + c[i] * p - m * a[i];
if (h[i] <= w) continue;
w = (h[i] - w - 1) / p + 1;
if (cnt + w > m * k) return 0;
cnt += w;
}
return 1;
}
int main() {
rd(n), rd(m), rd(k), rd(p);
for (int i = 1; i <= n; i++)
rd(h[i]), rd(a[i]),
l = max(l, a[i]), r = max(r, h[i] + m * a[i]);
while (l < r) {
ll o = (l + r) >> 1;
if (pd(o)) r = o;
else l = o + 1;
}
print(l);
return 0;
}
评论
暂无已公开评论。