题目

题意:在长为n的序列a[]中选2段不连续长度为k的区间使区间和最大。n ≤ 2e5


做法



代码

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 2e5 + 7;
const ll INF = 1e18;
int n, k, m, a[N];
ll prefix[N], rmq[N][18];
void init_rmq(void){
    for (int j = 1; (1<<j) <= m; ++j){
        for (int i = 1; i+(1<<j)-1 <= m; ++i){
            rmq[i][j] = max(rmq[i][j-1], rmq[i+(1<<(j-1))][j-1]);
        }
    }
}
ll ask_rmq(int l, int r){
    if (l > r) return -INF;
    int k = log2(r-l+1);
    return max(rmq[l][k], rmq[r-(1<<k)+1][k]);
}
int main(void){
    IOS;
    int T; cin >> T;
    while (T--){
        cin >> n >> k;
        for (int i = 1; i <= n; ++i){
            cin >> a[i];
            prefix[i] = prefix[i-1]+a[i];
        }
        m = n-k+1;
        for (int i = 1; i <= m; ++i){
            rmq[i][0] = prefix[i+k-1]-prefix[i-1];
        }
        init_rmq();
        ll ans = -INF;
        for (int i = 1; i <= m; ++i){
            ans = max(ans, rmq[i][0]+ask_rmq(i+k, m));
        }
        cout << ans << endl;
    }
    return 0;
}