CF985E Solution

题目链接

题解

dp+双指针,时间复杂度为\(O(n)\)

状态:\(dp[i]\):当前最右区间结尾为\(i\)时是/否(\(1/0\))可行。

初始值:\(dp[0]=1,dp[i]=0\quad(1\le i\le n)\)

转移方程:将\(a\)数组升序排序,设\(dp[i-1]\)\(dp[lst]\)转移而来。

\[dp[i]|=dp[j]\&(a_i-a_{j+1}\le d) \quad (1\le i\le n,lst\le j\le i-k) \]

因为\(a_i-a_{j+1}\)(排序后\(a_i,a_{j+1}\)分别为\([a_{j+1},a_i]\)的最大,最小值)随\(j\)增大单调递减,而\(dp[j]\)不变,所以\(j\)仅会右移。

目标状态:\(dp[n]\)

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N]; bool dp[N];
int main()
{
	int n,k,d,lst=0;
	scanf("%d%d%d",&n,&k,&d);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=lst;j<=i-k;j++)
		{
			if(dp[j]&(a[i]-a[j+1]<=d)) {dp[i]=1,lst=j; break;}
			if(j==i-k) lst=i-k+1;
		}
	}
	if(dp[n]) printf("YES");
	else printf("NO");
	return 0;
}
posted @ 2021-04-01 17:43  violet_holmes  阅读(53)  评论(0编辑  收藏  举报