『DP·单调队列』CodeForces - 985E Pencils and Boxes

P r o b l e m \mathrm{Problem} Problem

在这里插入图片描述
纠正luogu的一个mistake:是 ∣ a i − a j ∣ ≤ d . |a_i-a_j|\le d. aiajd.

S o l u t i o n \mathrm{Solution} Solution

我们可以采用DP的思想,设 f [ i ] f[i] f[i]表示到 i i i为止分成若干组的可行性。

显然我们可以通过排序,想原来的序列分成连续的几段。

那么就有: f [ i ] ∣ = f [ j ] ( i − j < k 且 a i − a j + 1 ≤ d ) f[i]|=f[j](i-j<k且a_i-a_{j+1}\le d) f[i]=f[j](ij<kaiaj+1d)

我们来考虑一下如何快速的解决这些限制。

由于数据元素单调递增,因此我们可以来维护一个单调队列。

  • 对于限制 i − j < k i-j<k ij<k来说,只要满足 f [ i − k ] = 1 f[i-k]=1 f[ik]=1就将 i − k + 1 i-k+1 ik+1加入队列。
  • 弹出首位差值过大的队头,直到满足条件位置,即 a [ i ] − a [ f r o n t ] ≤ d a[i]-a[\mathrm{front}]\le d a[i]a[front]d为止。

代码如下:

#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 6e5;

int n, m, k, d;
int a[N], f[N];

queue<int>q;

int read(void)
{
	int s = 0, w = 0; char c = getchar();
	while (c < '0' || c > '9') w |= c == '-', c = getchar();
	while (c >= '0' && c <= '9') s = s*10+c-48, c = getchar();
	return w ? -s : s;
}

int main(void)
{
	n = read(), k = read(), d = read();
	for (int i=1;i<=n;++i) a[i] = read();
	sort(a+1,a+n+1);
	f[0] = 1;
	for (int i=k;i<=n;++i)
	{
		if (f[i-k]) q.push(i-k+1);
		while (q.size() && a[i]-a[q.front()] > d) q.pop();
		f[i] = !q.empty();
	}
	puts(f[n] ? "YES" : "NO");
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值