P8484 Mole 题解
考虑 dp。
我们记
根据题意,状态有意义的范围为
转移就是枚举第
直接枚举
有同学这里会说,我会斜率优化啊,
斜率优化没错……但是你学傻了……
这玩意可以看作
没听过的话我直接放结论,两个数组做闵可夫斯基和,答案的差分数组是它俩的差分数组的归并。
(至于为啥
于是直接用这玩意转移复杂度
实现的时候发现,既然是差分归并,那直接维护
当
放个
#define N 5001
int dp[2][N], cnt, l, n; long long ans;
int main() {
rint(l); rint(n);
for (int i = 0, x; i < n; i++) {
rint(x);
int L = std::max(i-l+1, 0);
for (int j = L, p = L; j <= i && j <= n-l+1; j++)
dp[cnt][j] = dp[!cnt][p] > x ? dp[!cnt][p++] : x--;
if (i >= l-1) printf("%lld ", ans += dp[cnt][L]);
cnt = !cnt;
}
}
考虑优化,想想我们对
每一步相当于:
- 把
a[x],a[x]-1,\dots,1 的所有值加入S - 保留
S 中最大的l 个数字,其它的删掉 - 如果此时窗口已经开始滑动了,把
S 中最大的再删掉并计入答案
那么记
- 前缀所有位置
+1 - 二分一个前缀和,然后前缀清零(可能有一次单点修改)
- 找到最大值位置并
-1
这些操作都是线段树可以维护的。复杂度