题目要求求两个连续的区间和的最大值,我们可以先处理出两块区间和,然后加一起取max

法一、将两块区间和处理出来

fl[i]表示从1走到i位置,区间和长度为k的最大区间和
fr[i]表示从n走到i位置,区间和长度为k的最大区间和

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 200010;
const LL INF = 1e18;

int n, k;
LL fl[N], fr[N];
LL s[N];

int main() {
    int T; scanf("%d", &T);

    while (T -- ) {
      scanf("%d%d", &n, &k);
      for (int i = 1; i <= n; i ++ ) {
        scanf("%lld", &s[i]);
        s[i] += s[i - 1];
        fl[i] = fr[i] = -INF;
      }

      //表示[i - k + 1, i]的区间和
      for (int i = k; i <= n - k; i ++ )
        fl[i] = max(fl[i - 1], s[i] - s[i - k]);
      //表示[i, i + k - 1]的区间和
      for (int i = n - k + 1; i >= k + 1; i -- )
        fr[i] = max(fr[i + 1], s[i + k - 1] - s[i - 1]);

      LL ans = -INF;
      for (int i = k + 1; i <= n - k + 1; i ++ )
        ans = max(ans, fl[i - 1] + fr[i]);

      printf("%lld\n", ans);
    }
}

法二、先处理出右侧区间,遍历左区间

f[i]表示从n走到i位置的区间和

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 200010;

int n, k;
LL a[N];
LL s[N];
LL f[N];

int main() {
  int T; cin >> T;
  while (T -- ) {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++ ) {
      scanf("%lld", &a[i]);
      s[i] = s[i - 1] + a[i];
    }
    for (int i = 1; i <= n; i ++ )
      f[i] = -1e18;
    // memset(f, -0x3f, sizeof f);
    //右区间为[i, i + k - 1]的区间和中的最大值
    //f[n - k + 2] 就是等于0的,一开始没被更
    for (int i = n - k + 1; i >= k; i -- ){
      f[i] = max(f[i + 1], s[i + k - 1] - s[i - 1]);
    }

    LL ans = -1e18;
    //左区间为[i - k, i - 1]的区间和
    for (int i = k + 1; i <= n - k + 1; i ++ )
      ans = max(ans, s[i - 1] - s[i - k - 1] + f[i]);

    printf("%lld\n", ans);
  }

  return 0;
}

法三,简化

由上面的两个方法,我们看出,我们做的也是我们需要的就是让两个区间和最大化
若以i为分界点,就是求i之前的长度为k的区间和的最大值,和i后面的长度为k的区间和的最大值,我们可以一遍扫过

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 200010;
const LL INF = 1e18;

int n, k;
LL fl[N], fr[N];
LL s[N];

int main() {
    int T; scanf("%d", &T);

    while (T -- ) {
      scanf("%d%d", &n, &k);
      for (int i = 1; i <= n; i ++ ) {
        scanf("%lld", &s[i]);
        s[i] += s[i - 1];
        fl[i] = fr[i] = -INF;
      }

      LL ans = -INF, res = -INF;
      //以i为界,res表示从0开始,走到i的最大的长度为k的区间和
      for (int i = k; i <= n - k; i ++ ) {
        //s[i] - s[i - k]表示[i - k + 1, i]的区间和
        res = max(res, s[i] - s[i - k]);
        //s[i + k] - s[i]表示[i + 1, i + k]的区间和
        ans = max(ans, res + s[i + k] - s[i]);
      }

      printf("%lld\n", ans);
    }
}