cf Education Field 69D。さらに別のサブアレイ問題dp

質問https://codeforces.com/gym/297792/problem/D
質問の意味:サブシーケンス[l、r]のコストを指定してここに画像の説明を挿入
、この配列の最大コスト見つけます。

元のアイデア:最初に使用された方法は、ノードのストレージ間隔を定義し、長さlの各間隔の最大合計、および対応する左右のエンドポイントを見つけて、それらをadd配列に保存することです。ルーラーメソッドで各add [i]を更新します。最後に、addで各長さのコストを計算し、最大値を取得します。
このような考え方は正しいですが、残念ながら定規の時間コストが大きすぎて、直接タイムアウトします。
エラーコードは次のとおりです。

#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;
}

次に、解を調べたところ、これは実際にはバックパックdpであるdpで実行できることがわかりました。dp[i] [j]を使用して、iを右の境界dp [i]として連続するjの最大値を表します。 [j] = dp [i -1] [j-1]、jが0の場合、これは新しいm長セグメント(開始)、または前のm長セグメントからkを引いたものと同等であるためj = = 0、dp [i] [j] = max(a [i] -k、dp [i-1] [m-1] + a [i] -k);最終的な答えは、すべてのdpの最大値です。値。

コード:

#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;
}

おすすめ

転載: blog.csdn.net/u011612364/article/details/108922166