NC15553 数学考试


NC15553 数学考试

题目

题目描述

今天qwb要参加一个数学考试,这套试卷一共有 \(n\) 道题,每道题qwb能获得的分数为 \(a_i\) ,qwb并不打算把这些题全做完,
他想选总共 \(2k\) 道题来做,并且期望他能获得的分数尽可能的大,他准备选 \(2\) 个不连续的长度为 \(k\) 的区间,
\([L,L+1,L+2,\cdots,L+k-1]\)\([R,R+1,R+2,\cdots,R+k-1]\)\(R \geq L+k\))。

输入描述

第一行一个整数 \(T\)\(T<=10\)),代表有 \(T\) 组数据
接下来一行两个整数 \(n\) , \(k\) ,(\(2 \leq n \leq 200,000\)),(\(1 \leq k,2k \leq n\))
接下来一行 \(n\) 个整数 \(a_1,a_2,\cdots,a_n\) ,(\(-100,000 \leq a_i \leq 100,000\)

输出描述

输出一个整数,qwb能获得的最大分数

示例1

输入

2
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1

输出

6
7

题解

思路

知识点:前缀和(最大值)+枚举。

注意到两个区间是分别连续的且不重合,可以考虑枚举右区间左端点,同时更新可能左区间的最大值,最后更新答案最大值。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include 

using namespace std;

long long a[200007];
int main(){
    std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--){
        int n,k;
        cin>>n>>k;
        for(int i = 1;i<=n;i++){
            cin>>a[i];
            a[i] += a[i-1];
        }
        long long maxl = (1LL<<63),ans = (1LL<<63);
        for(int i = k;i<=n-k;i++){///枚举了所有的右区间+此右区间情况下的最大左区间值
            maxl = max(maxl,a[i]-a[i-k]);///更新最大左区间值
            ans = max(ans,maxl+a[i+k]-a[i]);///此右区间情况的左区间最大值+右区间值
        }
        cout<