Post

AcWing1087 - 修剪草坪

在一年前赢得了小镇的最佳草坪比赛后,FJ 变得很懒,再也没有修剪过草坪。

现在,新一轮的最佳草坪比赛又开始了,FJ 希望能够再次夺冠。

然而,FJ 的草坪非常脏乱,因此,FJ 只能够让他的奶牛来完成这项工作。

FJ 有 N 只排成一排的奶牛,编号为 1 到 N。

每只奶牛的效率是不同的,奶牛 i 的效率为 Ei。

编号相邻的奶牛们很熟悉,如果 FJ 安排超过 K 只编号连续的奶牛,那么这些奶牛就会罢工去开派对。

因此,现在 FJ 需要你的帮助,找到最合理的安排方案并计算 FJ 可以得到的最大效率。

注意,方案需满足不能包含超过 K 只编号连续的奶牛。

输入格式

第一行:空格隔开的两个整数 N 和 K;

第二到 N+1 行:第 i+1 行有一个整数 Ei。

输出格式

共一行,包含一个数值,表示 FJ 可以得到的最大的效率值。

数据范围

1≤N≤105, 0≤Ei≤109

输入样例:

1
2
3
4
5
6
5 2
1
2
3
4
5

输出样例:

1
12

样例解释

FJ 有 5 只奶牛,效率分别为 1、2、3、4、5。

FJ 希望选取的奶牛效率总和最大,但是他不能选取超过 2 只连续的奶牛。

因此可以选择第三只以外的其他奶牛,总的效率为 1 + 2 + 4 + 5 = 12。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#define int long long
using namespace std;
const int N = 100010;

int n, m;
int s[N], f[N], q[N];

int g(int i) {
  return f[i - 1] - s[i];
}

signed main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &s[i]);
    s[i] += s[i - 1];
  }
  
  int hh = 0, tt = 0;
  for (int i = 1; i <= n; i++) {
    if (q[hh] < i - m) hh++;
    f[i] = max(f[i - 1], g(q[hh]) + s[i]);
    while (hh <= tt && g(q[tt]) <= g(i)) tt--;
    q[++tt] = i;
  }
  
  printf("%lld\n", f[n]);
  
  return 0;
}
This post is licensed under CC BY 4.0 by the author.