题目描述
FJ 有 只排成一排的奶牛,编号为 到 。
每只奶牛的效率是不同的,奶牛 的效率为 。
编号相邻的奶牛们很熟悉,如果 FJ 安排超过 只编号连续的奶牛,那么这些奶牛就会罢工去开派对。
因此,现在 FJ 需要你的帮助,找到最合理的安排方案并计算 FJ 可以得到的最大效率。
注意,方案需满足不能包含超过 只编号连续的奶牛。
输入格式
第一行:空格隔开的两个整数 和 ;
第二到 行:第 行有一个整数 。
输出格式
共一行,包含一个数值,表示 FJ 可以得到的最大的效率值。
数据范围
,
输入样例:
5 2
1
2
3
4
5
输出样例:
12
样例解释
FJ 有 5 只奶牛,效率分别为 1、2、3、4、5。
FJ 希望选取的奶牛效率总和最大,但是他不能选取超过 2 只连续的奶牛。
因此可以选择第三只以外的其他奶牛,总的效率为 1 + 2 + 4 + 5 = 12。
题目分析
这是一道 单调队列优化DP 的问题。
像上题一样,本题需要多次求取区间和,则我们先将原数列转化为前缀和数列。
我们定义 表示前 头奶牛中,满足限制的奶牛的最大效率。
对于第 头奶牛,能与其产生关系的是下标为 的奶牛。我们假设从第 头奶牛开始,连续向前选择了 头奶牛,并且下标为 的奶牛不选,对于当前方案,其 。
则
将 提出,得
于是我们便可以利用单调队列维护上述 的最大值啦。
由于对于第一头牛而言,需要其前两个下标有效,则奶牛从 开始编号。
Accept代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100010;
int q[N], s[N], f[N];
int hh, tt = -1;
int n, m;
signed main()
{
cin >> n >> m;
for (int i = 2; i <= n + 1; i ++) cin >> s[i], s[i] += s[i - 1];
q[++ tt] = 1;
for (int i = 2; i <= n + 1; i ++)
{
if (q[hh] < i - m) hh ++;
while (hh <= tt && f[i - 1] - s[i] >= f[q[tt] - 1] - s[q[tt]]) tt --;
q[++ tt] = i;
f[i] = s[i] + f[q[hh] - 1] - s[q[hh]];
}
cout << f[n + 1];
return 0;
}