2018.09.10【BZOJ2442】修剪草坪(单调队列优化DP)

传送门


解析:

首先状态转移还是比较好想的。
f i , 0 / 1 f_{i,0/1} fi,0/1表示考虑前 i i i个时,选择第 i i i个与不选第 i i i个能够获得的最大效益。
我们维护一个 s u m sum sum数组表示前缀和。

那么,状态转移方程也就呼之欲出了
f i , 0 = m a x ( f i − 1 , 0 , f i − 1 , 1 ) f_{i,0}=max(f_{i-1,0},f_{i-1,1}) fi,0=max(fi1,0,fi1,1)
f i , 1 = m a x ( f j , 0 − s u m j ) + s u m i ( i − k &lt; = j &lt; i ) f_{i,1}=max(f_{j,0}-sum_j)+sum_i(i-k&lt;=j&lt;i) fi,1=max(fj,0sumj)+sumi(ik<=j<i)
显然可以使用单调队列优化。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static

inline
ll getint(){
	re ll num=0;
	re char c;
	while(!isdigit(c=gc()));
	while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
	return num;
}

int n,k;
ll sum[100002];
ll f[100002][2];
ll q[100002];
int head=1,tail=1;

signed main(){
	n=getint();
	k=getint();
	for(int re i=1;i<=n;++i)sum[i]=sum[i-1]+getint();
	
	for(int re i=1;i<=n;++i){
		f[i][0]=max(f[i-1][0],f[i-1][1]);
		while(q[head]<i-k&&head<=tail)++head;
		f[i][1]=f[q[head]][0]-sum[q[head]]+sum[i];
		while(f[i][0]-sum[i]>f[q[tail]][0]-sum[q[tail]]&&tail>=head)--tail;
		q[++tail]=i;
	}
	
	cout<<max(f[n][0],f[n][1]);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值