蒟蒻君的刷题日记Day16(DP专题T5):CF467C George and Job
作者:互联网
解题思路
很明显的 dp 题。
-
状态定义:令 d p [ i ] [ j ] dp[i][j] dp[i][j] 为 n = i , k = j n=i,k=j n=i,k=j 时选出最后一个数的答案。
-
状态转移方程:
因为第 i i i 个数必须选出,且为数组中最后一个数,则必须是一个子序列的结尾。我们再枚举一下上一个子序列的结尾,取最优即可。 -
优化:单调队列优化,前缀和预处理所有子序列的和。
代码实现
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5005;
int a[N], s[N], q[N], dp[N][N];
signed main() {
ios :: sync_with_stdio(0);
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
int res = 0;
for (int j = 1; j <= k; ++j) {
memset(q, 0, sizeof q);
int head = 1, tail = 1;
for (int i = m; i <= n; ++i) {
if (head <= tail) {
dp[i][j] = max(dp[i][j], dp[q[head]][j - 1] + s[i] - s[i - m]);
}
while (head <= tail && dp[i - m + 1][j - 1] > dp[q[tail]][j - 1]) {
--tail;
}
q[++tail] = i - m + 1;
res = max(res, dp[i][k]);
}
}
cout << res << '\n';
return 0;
}
标签:head,CF467C,int,res,T5,tail,Job,序列,dp 来源: https://blog.csdn.net/yueyuedog/article/details/122877428