题目链接:https://loj.ac/problem/10177
解题思路
我们设dp[i][0]表示以i为结尾不选i的最大值,dp[i][1]表示以i为结尾选i的最大值。
我们可以得到以下状态转移方程。
其中dp[i][1]可以继续转化。
我们将sum[i]提取出来。
我们发现后面是求一段连续区间内的最大值,所以可以用单调队列优化,复杂度O(n)。
AC代码
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node
{
int pos;
ll val;
}q[N];
ll dp[N][2];//dp[i][0]表示以i为结尾不选i的最大值,dp[i][1]表示以i为结尾的选i的最大值
ll E[N],sum[N];
int n,k,l,r;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%lld",&E[i]);
sum[i]=sum[i-1]+E[i];
}
q[r].val=0;
q[r++].pos=0;
for(int i=1;i<=n;++i)
{
while(l<r&&(i-q[l].pos)>k)
l++;
dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
dp[i][1]=sum[i]+q[l].val;
//cout<<dp[i][0]<<" "<<dp[i][1]<<endl;
//cout<<q[l].pos<<" "<<q[l].val<<endl;
ll v=dp[i][0]-sum[i];
//cout<<v<<endl;
while(l<r&&v>=q[r-1].val)
r--;
q[r].val=v;
q[r++].pos=i;
}
printf("%lld\n",max(dp[n][0],dp[n][1]));
return 0;
}