修剪草坪 单调队列优化DP
// 修剪草坪.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstring>
#include <deque>
using namespace std;
/*
https://loj.ac/p/10177
http://ybt.ssoier.cn:8088/problem_show.php?pid=1599
原题来自:USACO 2011 Open Gold
在一年前赢得了小镇的最佳草坪比赛后,FJ 变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,FJ 希望能够再次夺冠。
然而,FJ 的草坪非常脏乱,因此,FJ 只能够让他的奶牛来完成这项工作。FJ 有 N只排成一排的奶牛,编号为 1到 N。
每只奶牛的效率是不同的,奶牛 i 的效率为 Ei。
靠近的奶牛们很熟悉,如果 FJ 安排超过 K只连续的奶牛,那么这些奶牛就会罢工去开派对。
因此,现在 FJ 需要你的帮助,计算 FJ 可以得到的最大效率,并且该方案中没有连续的超过 K只奶牛。
【输入】
第一行:空格隔开的两个整数 N 和 K;
第二到 N+1 行:第 i+1行有一个整数 Ei。
【输出】
一行一个值,表示 FJ 可以得到的最大的效率值。
【输入样例】
5 2
1
2
3
4
5
【输出样例】
12
【提示】
样例说明:
FJ 有 5
只奶牛,他们的效率为 1,2,3,4,5。
他们希望选取效率总和最大的奶牛,但是他不能选取超过 2
只连续的奶牛。FJ 选择出了第三只以外的其他奶牛,总的效率为 1+2+4+5=12。
数据范围与提示:
对于全部数据,1≤N≤105,0≤Ei≤109。
6 1
4
7
2
0
8
9
10 3
16
28
37
8
47
30
36
6
0
37
237
*/
const int N = 100010;
long long pre[N];
long long dp[N];
int lastZero;
int n, k;
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++) {
int t; cin >> t;
pre[i] = pre[i - 1] + t;
}
deque<int> q;
for (int i = 1; i <= n; i++) {
/*
if (i <= k) {
dp[i] = pre[i];
}
else {
for (int lastzero = i; lastzero >= i - k; lastzero--) {
dp[i] = max(dp[i], dp[lastzero - 1] + pre[i] - pre[lastzero]);
}
}
*/
while (!q.empty() && i - q.front() > k)
q.pop_front();
if (q.empty() || i<=k)
dp[i] = pre[i];
else {
dp[i] = (dp[q.front()-1] - pre[q.front()] + pre[i]);
}
while (!q.empty() && (dp[q.back()-1] - pre[q.back()] <= dp[i-1] - pre[i]))
q.pop_back();
q.push_back(i);
}
cout << dp[n] << endl;
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
![阿里打赏](https://files.cnblogs.com/files/itdef/ali2.bmp)
![微信打赏](https://files.cnblogs.com/files/itdef/weixin2.bmp)