【ybt金牌导航1-4-3】【luogu P2627】修剪草坪 / Mowing the Lawn G

修剪草坪 / Mowing the Lawn G

题目链接:ybt金牌导航1-4-3 / luogu P2627

题目大意

有一个序列,你要在里面选一个序列,使得不会有超过 k 个数是在原序列中相邻的。

思路

我们先看到在序列中选要的好像没有什么思路,那我们考虑选哪些是不选的。

那我们就会发现我们可以进行 DP。
f i f_i fi 为前 i i i 个数,满足题目的要求,且第 i i i 个不选,不选的数的和的最小值。
那容易得出转移方程:( f 0 = 0 f_0=0 f0=0 显然)
f i = e i + min ⁡ j = max ⁡ { i − k − 1 , 0 } i − 1 f j f_i=e_i+\min\limits_{j=\max\{i-k-1,0\}}^{i-1}f_j fi=ei+j=max{ik1,0}mini1fj

那你可以发现它这个 min ⁡ \min min 可以用单调队列来维护,然后就好了。

代码

#include<cstdio>
#include<iostream>
#define ll long long

using namespace std;

int n, k, l, r, a[100001];
ll e[100001], f[100001], sum, ans = 1e15;

int main() {
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++) scanf("%lld", &e[i]), sum += e[i];
	
	k++;
	f[1] = e[1];
	l = 1;
	r = 1;
	for (int i = 1; i <= n; i++) {//单调队列
		while (a[l] < i - k && l <= r) l++;
		f[i] = f[a[l]] + e[i];//dp转移
		while (f[i] <= f[a[r]] && l <= r) r--;
		a[++r] = i;
	}
	
	for (int i = max(0, n - k + 1); i <= n; i++)
		ans = min(ans, f[i]);//枚举最后一个不选的位置在哪里
	
	printf("%lld", sum - ans);
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值