题目链接:点击打开链接
思维很重要,首先要把这个问题抽象成模型。即能否用若干个盒子装下n个物品,每个盒子里的物品价值范围为ai,aj和ai到aj区间内的所有物品。
用dp【i】表示从i到n个物品能否按规则装下,是为1,否为0;
先将从小到大数组排序
考量一个dp【i】时只需考量dp【i+k+1】,dp【i+k+2】。。。dp【x】(a【x】为upper_bound(a【i】+d+1))
其中若有一个dp值为1,那么dp【i】就为1。
从后向前dp,最后的结果取决于dp【1】;
判断时因为i+d可能大于n,所以细节处理至关重要,注意特判k==1的情况
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,n,m) for(int i=n;i>=m;i--)
#define lan(a,b) memset(a,b,sizeof(a))
#define maxn 500010
using namespace std;
LL shu[maxn];
LL a[maxn];
int dp[maxn];
int n,k,d;
int lowbit(int i)
{
return i&(-i);
}
int query(int i)
{
int ans=0;
while(i)
{
ans+=shu[i];
i-=lowbit(i);
}
return ans;
}
void update(int p,int i)
{
while(i<=n )
{
shu[i]+=p;
i+=lowbit(i);
}
}
int main()
{
while(~scanf("%d%d%d",&n,&k,&d))
{
lan(a,0);
lan(shu,0);
lan(dp,0);
For(i,1,n)
scanf("%lld",&a[i]);
if(k==1)
{
printf("YES\n");
continue;
}
sort(a+1,a+1+n);
dp[n]=0;
update(0,n);
for(int i=n-1;i>=1;i--)
{
int t1=i+k-1;
int t2=upper_bound(a+1,a+1+n,a[i]+d)-a-1;
//cout << i << " " << t1 << " " << t2 << endl;
if(t1>t2)
{
dp[i]=0;
update(0,i);
continue;
}
if(t2==n)
{
dp[i]=1;
update(1,i);
// cout << dp[i] << endl;
continue;
}
// printf("query=%d\n",query(t2+1)-query(t1));
if(query(t2+1)-query(t1))
{
dp[i]=1;
update(1,i);
}
else
{
dp[i]=0;
update(0,i);
}
//cout << dp[i] << endl;
}
if(dp[1])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}