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



京公网安备 11010502036488号