题目链接 数学考试
题意
今天qwb要参加一个数学考试,这套试卷一共有n道题,每道题qwb能获得的分数为ai,qwb并不打算把这些题全做完,
他想选总共2k道题来做,并且期望他能获得的分数尽可能的大,他准备选2个不连续的长度为k的区间,
即[L,L+1,L+2,….,L+k-1],[R,R+1,R+2,…,R+k-1](R >= L+k)。
思路
一开始我想的非常复杂,求完前缀和后要进行一系列的贪心操作,但是做到一半行不通,但是我发现了动态规划的做法,就是对于每个区间来说,都需要加上后面值最大的区间,那么我就先用一个dp数组从后往前扫,储存从最后一位到第i个区间的最大值。然后再从前往后扫输出最大值即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = (int) 2e5+7;
const ll INF = (ll) 0x3f3f3f3f3f3f3f3f;
int N,K;
ll A[MAXN];
ll Sum[MAXN];
ll dp[MAXN]; //存的是从后往前的最大值
int main()
{
ios::sync_with_stdio(false);
int T;
cin >> T;
while (T --){
cin >> N >> K;
for (int i = 1;i <= N;i ++) {
cin >> A[i];
Sum[i] = Sum[i-1] + A[i];
}
fill (dp,dp+MAXN,-INF);
for (int i = N-K+1;i > 0;i --){
dp[i] = max(dp[i+1],Sum[i+K-1]-Sum[i-1]);
}
ll mn = -INF;
for (int i = 1;i+K-1 <= N;i ++){
mn = max(mn,dp[i+K] + Sum[i+K-1]-Sum[i-1]);
}
cout << mn << endl;
}
}
/*
3
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1
4 2
2 2 1 1
*/