思路
模板题:
一般这种题就是先枚举一个区间的左端点,然后用数据结构维护另外一个区间左端点选择。
如下图
如果枚举一个区间的左端点选择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; }