今天的考试题目中有单调队列优化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; }