0, 1, 2…i - j - 1, |i - j|, i - j + 1,....i;
j表示连续选择的长度j <= m,从i - j + 1 ~ i共连续选了j个数,则不选|i - j|
f(i):
不选i: f(i) = f(i - 1);
选择i: f(i) = f(i - j - 1) + s(i) - s(i - j);
|i-j| 右边根据前缀和公式s(r) - s(l - 1) 中: r = i, l = i - j + 1
|i-j| 左边即为 f(i - j - 1) 的最大值
选i时 f(i) = max(f(i - j - 1) + s(i) - s(i - j)) = max(f(i - j - 1) - s(i - j)) + s(i);
f(i - j - 1) - s(i - j) 使用 g(i - j)记录, j 表示长度, q[hh] = i - j 表示!起点前一个点位置!即g(q[hh]);
import java.util.*;
class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
long[] s = new long[n+1];
for(int i = 1; i <= n; i++){
s[i] = sc.nextInt();
s[i] += s[i-1];
}
long[] f = new long[n+1];
long[] g = new long[n+1];
int[] q = new int[n+1];
int hh = 0, tt = -1; //将g[0]加入到队列中,否则会从g[1]开始考虑忽略g[0]
q[++tt] = (int) g[0];
for(int i = 1; i <= n; i++){
if(hh <= tt && i - q[hh] > m) hh++;
g[i] = f[i-1] - s[i];
f[i] = Math.max(f[i-1], g[q[hh]] + s[i]);
while(hh <= tt && g[q[tt]] <= g[i]) tt--;
q[++tt] = i;
}
System.out.println(f[n]);
}
}
### 你这个全篇加粗让我有点迷茫
不太会写,格式排版有点丑,就。。。