【优化】单调队列与dp

匿名 (未验证) 提交于 2019-12-02 23:49:02

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

持续更新中。

 

转载请标明出处:【优化】单调队列与dp
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!