链接:https://ac.nowcoder.com/acm/contest/24213/1013
来源:牛客网
来源:牛客网
题目描述
今天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)。
他想选总共2k道题来做,并且期望他能获得的分数尽可能的大,他准备选2个不连续的长度为k的区间,
即[L,L+1,L+2,....,L+k-1],[R,R+1,R+2,...,R+k-1](R >= L+k)。
输入描述:
第一行一个整数T(T<=10),代表有T组数据 接下来一行两个整数n,k,(2<=n<=200,000),(1<=k,2k <= n) 接下来一行n个整数a1,a2,...,an,(-100,000<=ai<=100,000)
输出描述:
输出一个整数,qwb能获得的最大分数
题型:
动态规划--求2个没有交集的长度固定的区间的最大值总和
思路:
1.明确原问题:求2个没有交集的长度为k的区间的最大值总和
2.明确子问题:求出1个长度为k的区间的最大值-->如何求出数组上某个长度为k的区间的值-->考虑用前缀和sum[]来求,即dp[i]=sum[i]-sum[i-k]
3.明确状态转移方程:dp[i]=max(dp[i-1],sum[i]-sum[i-k])(注意:i>=k),这个方程能够求出1个长度为k的区间的最大值
4.转化成求2个长度为k的区间的最大值,即可以开两个dp[]数组,一个记录从左边开始的长度为k的区间的最大值,即dp[i]=max(dp[i-1],sum[i]-sum[i-k])(注意:i>=k && i<=n-k(<=n-k是为了防止其与最右边的区间有交集)),另一个记录从右边开始的长度为k的区间的最大值,即dp[i]=max(dp[i+1],sum[i+k-1]-sum[i-1])(注意:i>=k+1 && i<=n-k+1(>=k+1是为了防止其与最左边的区间有交集))
5.最后求两个区间的最大值总和,即ans=max(ans,dp左[i]+dp右[i]);(i>=k && i<=n-k)
代码:
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
ll a[200200],sum[200200],dpl[200200],dpr[200200],ans;
int main(){
int T,n,k;
scanf("%d",&T);
while(T--){
ans=-9999999999999999;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++){
dpl[i]=-9999999999999999;
dpr[i]=-9999999999999999;
}
for(int i=n-k+1;i>=k+1;i--){
dpr[i]=max(dpr[i+1],sum[i+k-1]-sum[i-1]);
}
for(int i=k;i<=n-k;i++){
dpl[i]=max(dpl[i-1],sum[i]-sum[i-k]);
ans=max(ans,dpl[i]+dpr[i+1]);
}
printf("%lld\n",ans);
}
return 0;
}
#define ll long long int
using namespace std;
ll a[200200],sum[200200],dpl[200200],dpr[200200],ans;
int main(){
int T,n,k;
scanf("%d",&T);
while(T--){
ans=-9999999999999999;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++){
dpl[i]=-9999999999999999;
dpr[i]=-9999999999999999;
}
for(int i=n-k+1;i>=k+1;i--){
dpr[i]=max(dpr[i+1],sum[i+k-1]-sum[i-1]);
}
for(int i=k;i<=n-k;i++){
dpl[i]=max(dpl[i-1],sum[i]-sum[i-k]);
ans=max(ans,dpl[i]+dpr[i+1]);
}
printf("%lld\n",ans);
}
return 0;
}