牛客每日一题3月

目录:

1.3.27  NC15553.数学考试(线性DP)

 

NC15553.数学考试(线性DP)

题意:

给一个长度为n的数组,求在数组中求出两个不相交且长度为k的最大子段和

思路:

可以先预处理出一个前缀和sum[i]=a[1]+a[2]+..a[i],方便直接计算任意子段的和

之后定义dp[i]为从1到i中以i为终点的长度为k的最大子段和,所以dp[i]仅在i≥k时有定义

最后我们可以通过循环遍历,不断更新dp[i],并且在i≥2k之后开始记录答案,ans=max(dp[i-k]+sum[i]-sum[i-k],ans)

要注意初始化答案与dp[i]为负无穷

#include<iostream>
#include<algorithm>
#include<cstring>
 using namespace std;
 const int maxn=2e5+10;
 typedef long long ll;
 ll dp[maxn],sum[maxn],a[maxn];
 int main()
 {
     int t,n,k;
     scanf("%d",&t);
     while(t--){
         scanf("%d%d",&n,&k);
         ll ans=-1ll<<60;
         for(int i=1;i<=n;i++){
             scanf("%lld",&a[i]);
             sum[i]=a[i]+sum[i-1];
             dp[i]=-1ll<<60;
         } 
        for(int i=k;i<=n;i++){
            dp[i]=max(dp[i-1],sum[i]-sum[i-k]);
            if(i>=2*k){
                ans=max(sum[i]-sum[i-k]+dp[i-k],ans);
            }        
        }
        cout<<ans<<endl;
     }
    return 0;
 }
View Code

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12579278.html