[单调队列优化DP]JZOJ 3128 跳格子
Posted mastervan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[单调队列优化DP]JZOJ 3128 跳格子相关的知识,希望对你有一定的参考价值。
分析
我们可以贪心的思考一下,先考虑只跳正数钱的格子,那我们设s[i]为1..i中所有正数的和
f[i]为跳到i且i-1作为跳回来的格子的最大钱数,那么方程还算挺明显的:f[i]=max{f[j]+s[i-2]-s[j]}+v[i]+v[i-1]
然后最后答案是max{f[i]+s[i+k-1]-s[i]}
然后f[j]-s[j]这一段是可以用单调队列优化的 就很简单啦
#include <iostream> #include <cstdio> #include <queue> using namespace std; typedef long long ll; const int N=2.5e5+10; int pos[N]; deque<ll> q; int n,k,l,r; ll v[N],s[N],ans,f[N]; int main() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%lld",&v[i]),s[i]=s[i-1]+(v[i]<0ll?0ll:v[i]); l=1;r=0; for (int i=2,j=0;i<=n;i++,j++) { ll now=f[j]-s[j]; while (!q.empty()&&q.back()<=now) q.pop_back(),r--; q.push_back(now);pos[++r]=j; while (!q.empty()&&pos[l]<i-k) l++,q.pop_front(); f[i]=q.front()+s[i-2]+v[i-1]+v[i]; } ans=f[1]+s[min(1+k,n)]; for (int i=2;i<=n;i++) { ans=max(ans,f[i]+s[min(i+k-1,n)]-s[i]); } printf("%lld",ans); }
以上是关于[单调队列优化DP]JZOJ 3128 跳格子的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1499[NOI2005]瑰丽华尔兹 单调队列优化dp
Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP