cf Education Field 69 D. Yet Another Subarray Problem dp

Question https://codeforces.com/gym/297792/problem/D
Question meaning: Specify the cost of subsequence [l, r] to Insert picture description here
find the maximum cost of this array.

The original idea: the method used at the beginning is to define a node storage interval, find the maximum sum of each interval of length l, and the corresponding left and right endpoints, and save them to the add array. Update each add [i] with the ruler method. Finally, calculate the cost for each length in add, and just take the maximum value.
This kind of thinking is correct, but unfortunately the time cost of the ruler is too large, and it directly times out.
The error code is as follows:

#include <bits/stdc++.h>
#include <algorithm>
#include<iostream>
#include <stdio.h>
#define INF 0x3f3f3f3f
const int maxn=300005;
using namespace std;
typedef long long ll;
ll a[maxn];
ll pre[maxn];
//int vis[maxn];
struct node{
    
    
    ll l,r;
    ll sum;
}add[maxn];
int main(){
    
    
    ll n,m,k;
    cin>>n>>m>>k;
    pre[0]=0;
    a[0]=0;
    for(ll i=1;i<=n;i++){
    
    
        cin>>a[i];
        pre[i]=pre[i-1]+a[i];
    }
    add[n].sum=pre[n];
    add[n].l=1;
    add[n].r=n;

    for(ll i=n-1;i>=1;i--){
    
    
        ll left=1;
        ll right=left+i-1;
        ll sum=pre[right];
        add[i].sum=sum;
        while(right<=n){
    
    
            sum-=a[left];
            left++;
            right++;
            sum+=a[right];
            add[i].sum=max(add[i].sum,sum);
        }
    }
    ll sum=0;
    ll ans=0;
    for(ll i=1;i<=n;i++){
    
    
        ll cushu=(i-1)/m+1;
        sum=add[i].sum-k*cushu;
        ans=max(sum,ans);
    }
    cout<<ans<<endl;
    return 0;
}

Then I looked at the solution and found that this can be done with dp, which is actually a backpack dp. Use dp[i][j] to represent the maximum value of consecutive j with i as the right boundary, dp[i][j]=dp[i -1][j-1], when j is 0, it is equivalent to a new m-length segment, which may be the beginning, or the previous m-length segment minus k so j==0, dp[i ][j]=max(a[i]-k,dp[i-1][m-1]+a[i]-k); The final answer is the maximum value of all dp values.

Code:

#include <bits/stdc++.h>
#include <algorithm>
#include<iostream>
#include <stdio.h>
#define INF 0x3f3f3f3f
const int maxn=300005;
using namespace std;
typedef long long ll;
ll a[maxn];
ll dp[maxn][20];

int main(){
    
    
    ll n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    ll ans=0;
    for(ll i=1;i<=n;i++){
    
    
        for(ll j=0;j<min(i,m);j++){
    
    
            if(j==0)
                dp[i][j]=max(a[i]-k,dp[i-1][m-1]+a[i]-k);
            else
                dp[i][j]=dp[i-1][j-1]+a[i];
            ans=max(ans,dp[i][j]);
        }
    }
    cout<<ans<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/u011612364/article/details/108922166