思路
模板题:
一般这种题就是先枚举一个区间的左端点,然后用数据结构维护另外一个区间左端点选择。


如下图
图片说明
如果枚举一个区间的左端点选择i点,那么另外一个区间左端点的选择情况只有5种情况。
如果枚举一个区间的左端点选择(i - 1)点(图中未画出),那么另外一个区间左端点的选择情况只有6(5+1(i + k - 1)为左端点)种情况。
发现没,这样就可以不断维护左端点选择为[i + k, n + k - 1]的最大值。


其实这道题也可以暴力用线段树搞,只不过代码量大一点常数大一点,哈哈。


卧槽,刚刚发现连优先队列都不需要用,毕竟维护后缀最大值,直接O(n)就可以了
所以总复杂度就是O(T * n)


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const ll inf = 2e18;
//priority_queue<ll> que;
ll a[maxn], sum[maxn];
int n, k;
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        //while(!que.empty()) que.pop();
        ll ma = -inf;
        ll tmp = 0; ll ans = -inf;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
            tmp += a[i];
            if(i >= k){
                sum[i - k + 1] = tmp; tmp -= a[i - k + 1];
            }
        }
        for(int j = n; j >= 1; j--){
            int i = j - k;
            if(n - j + 1 >= k && i >= 1){
                //que.push(sum[j]);
                ma = max(ma, sum[j]);
                tmp = ma + sum[i];
                ans = max(ans, tmp);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}