dp[i][1]=max{dp[j][0]-sum[j]+sum[i]},i-k<=j<i
dp[i][1]=max{dp[j][0]-sum[j]}+sum[i].
s[q[head]]-f[q[head]][0]>s[i]-f[i][0]&&head<=tail
#include<cstdio> #include<iostream> using namespace std; long long q[2000000],f[2000000][2]; long long n,k,s[2000000],a[2000000]; long long tail,head; int main(){ scanf("%lld%lld",&n,&k); for(int i=1;i<=n;++i){ scanf("%lld",&a[i]); s[i]=s[i-1]+a[i];//sum } tail=head=1;//初始化 for(int i=1;i<=n;++i){ f[i][0]=max(f[i-1][0],f[i-1][1]);//对于不选i,只考虑前面两个即可 while(q[head]<i-k&&head<=tail)head++;//判断队头是否在所找区间内 f[i][1]=f[q[head]][0]-s[q[head]]+s[i];//取MAX转移 while(f[i][0]-s[i]>f[q[tail]][0]-s[q[tail]]&&head<=tail)tail--; q[++tail]=i;//更新队尾,当队列有数且当前队尾若插入i不满足单调性时 //写成s[i]-f[i][0]<s[q[tail]]-f[q[tail]][0]也可以 //可以理解为选到i和队尾时,两者不选的奶牛的效率和相比较,显然浪费少的更优,不优的删除即可 }printf("%lld\n",max(f[n][0],f[n][1])); return 0; }
双倍经验:P2034
持续更新中。