今天的考试题目中有单调队列优化dp的,感觉不太熟练,所以练几手题
其实这题就是今天的T2!!!!
首先是dp很明确
dp[i,0]表示处理了前i个位置,并且第i个位置不选的最大值
dp[i,1]表示处理了前i个位置,并且第i个位置要选的最大值
明显dp[i,0]=max(dp[i-1,0],dp[i-1,1]);
dp[i,1]=dp[j,0]+sum[i]-sum[j],(i-k<=j<i)
又是维护移动区间,维护递减的单调队列
code by wzxbeliever:
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ri register int
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=1e5+5;
int n,k,head=1,tail=1;
il ll maxl(ll a,ll b){if(a>b)return a;return b;}
ll num[maxn],a[maxn],sum[maxn],dp[maxn][2];
int main(){
scanf("%d%d",&n,&k);
for(ri i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
for(ri i=1;i<=n;i++){
dp[i][0]=maxl(dp[i-1][0],dp[i-1][1]);
while(head<=tail&&num[head]<i-k)head++;
dp[i][1]=dp[num[head]][0]-sum[num[head]]+sum[i];
while(head<=tail&&dp[i][0]-sum[i]>dp[num[tail]][0]-sum[num[tail]])tail--;
num[++tail]=i;
}
printf("%lld\n",maxl(dp[n][0],dp[n][1]));
return 0;
}