リンクリンク l i n k
質問の意味:長さnnnの配列。そこから複数のセグメントを取得でき、各セグメントの長さはKKを超えることはできませんK、いくつかのセグメントの最大値はいくつですか?
解:
dp [i] [0] = max(dp [i-1] [0]、dp [i-1] [1])dp [i] [0] = max(dp [i-1] [0 ]、dp [i-1] [1])d p [ i ] [ 0 ]=m a x (d p [ i−1 ] [ 0 ] 、d p [ i−1 ] [ 1 ] ) ;
dp [i] [1] = max(dp [k] [0] + sum [i]-sum [k])dp [i] [1] = max(dp [k] [0] + sum [i] -sum [k])d p [ i ] [ 1 ]=m a x (d p [ k ] [ 0 ]+s u m [ i ]−s u m [ k ] )其中(i − K <= k <= i)(iK <= k <= i)(私−K<=k<=i ) ;
化简得:dp [i] [1] = sum [i]-max(dp [k] [0]-sum [k])dp [i] [1] = sum [i] -max( dp [k] [0] -sum [k])d p [ i ] [ 1 ]=s u m [ i ]−m a x (d p [ k ] [ 0 ]−s u m [ k ] )其中(i − K <= k <= i)(iK <= k <= i)(私−K<=k<=i ) ;
そして、ここでmax(dp [k] [0]-sum [k])max(dp [k] [0] -sum [k])m a x (d p [ k ] [ 0 ]−s u m [ k ] )は、キューをポーンすることで取得できます。
コード:コード: c o d e :
#include <bits/stdc++.h>
#define ll long long
#define pi pair<int,int>
#define mk make_pair
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
ll a[maxn],q[maxn],sum[maxn],dp[maxn][2];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%lld",a+i),sum[i] = sum[i-1] + a[i];
k+=1;
int head = 1,tail = 0;
for(int i=1;i<=n;i++)
{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]);
while(head <= tail && i-q[head]+1 > k)++head;
while(head <= tail && dp[q[tail]][0] - sum[q[tail]] < dp[i][0] - sum[i])--tail;
q[++tail] = i;
if(i < k)dp[i][1] = sum[i];
else dp[i][1] = sum[i] + dp[q[head]][0] - sum[q[head]];
}
printf("%lld\n",max(dp[n][0],dp[n][1]));
return 0;
}