P1484 种树 Sol / wqs 二分
不会反悔贪心,所以用 wqs 二分解决了问题。
首先可以发现对于函数 (表示强制选 个点时的最大点权和)来说,它呈上凸壳状。
原因是每一次都应当加入使得答案变得最大的一个点。
否则可以交换两次操作使得答案更优,不符合题意。
到了某个 之后,你被迫选择不那么优的点(本题中为负点权),所以答案会下降。
所以 呈现上凸壳状。
wqs 二分的思想是二分斜率。对于当前二分到的斜率 ,可以确定一条直线 。
由于我们无法知道 的值(不然为什么还要二分呢对吧),考虑用 来反推 。
由于 确定,使得 最大,就要使得 最大(即直线截距最大)。
考虑 ,可以想到,它等效于每一次花费 的代价来进行一次答案更新。
那么如何求出 呢?考虑将每一个原点权 ,跑一遍 DP,求出最大点权和以及最大点权和选择的点数。
如果当前选择的点数 ,意味着当前的斜率 是可行的,可以继续减小,记录答案。
否则,当前的 不可行,斜率需要继续增大。
由于你求出的点数其实就是 ,所以我们可以将求出来的答案 以获得真实答案。
当然,在这之前,分情况考虑。
由于题目说“至多 次”,所以对于 对应的 时,直接输出 即可。
也就是说对于在 单调减的区间内的 ,我们不如直接选在这之前的最大值。
接下来只需要考虑 单调递增的情况,像前面那样处理即可。
但是有一个问题,就是存在特殊情况,点权可以重复,即一段斜率可能相等。
这里我们就可以简单粗暴地处理问题,将求出来的答案 。
虽然说对于和 处斜率不一致的 求出来的答案是错误的,但是我们只关心最大值。
在这段区间内, 越大,答案越大, 时自然最优;且点数单调非降,不会对最大值产生影响,答案自然正确。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10, inf = 1e18;
int n, k, a[N], dp[N][2], g[N][2];
inline pair <int, int> check(int mid) {
for (int i = 1; i <= n; ++i) {
dp[i][0] = dp[i - 1][0], g[i][0] = g[i - 1][0];
if (dp[i - 1][1] >= dp[i][0]) {
if (dp[i][0] == dp[i - 1][1]) g[i][0] = min(g[i][0], g[i - 1][1]);
else g[i][0] = g[i - 1][1], dp[i][0] = dp[i - 1][1];
}
dp[i][1] = dp[i - 1][0] + a[i] - mid, g[i][1] = g[i - 1][0] + 1;
}
if (dp[n][0] > dp[n][1]) return {dp[n][0], g[n][0]};
if (dp[n][0] == dp[n][1]) return {dp[n][0], min(g[n][0], g[n][1])};
return {dp[n][1], g[n][1]};
}
signed main() {
ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
cin >> n >> k; for (int i = 1; i <= n; ++i) cin >> a[i];
auto tmp = check(0); if (tmp.second <= k) return cout << tmp.first << endl, 0;
int l = 1, r = *max_element(a + 1, a + 1 + n), res;
while (l <= r) {
int mid = (l + r) >> 1; auto tmp = check(mid);
int val = tmp.first, num = tmp.second;
if (num <= k) res = val + k * mid, r = mid - 1;
else l = mid + 1;
}
cout << res << endl;
return 0;
}
本文作者:MistZero
本文链接:https://www.cnblogs.com/MistZero/p/P1484-Sol.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步