E. Pencils and Boxes 题解(双指针+dp)
题目链接
题目大意
你有 n 只铅笔,每个铅笔的饱和度是 a[i]。
现在你要把铅笔放进盒子里,盒子可以有任意个,但是每个盒子里至少要放 k 只铅笔。
并且对于一个盒子里任意两只铅笔 i 和 j 必须满足他们的饱和度差异不超过 d
即 |a[i] - a[j]| ≤ d问是否存在一种可行的放法。
1 ≤ k ≤ n ≤ 500000, d, a[i] ≤ 10^9
题目思路
其实仔细思考是一个很简单的dp
显然我们发现把 a 数列排序后按顺序划分一定是最优的。
因此我们可以先对 a 数列从小到大排序,然后用 \(dp[i]\)表示能否把前 i 个放进盒子里
然后再用双指针和前缀和优化下dp即可
代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=5e5+5,inf=0x3f3f3f3f,mod=1234567891;
const double eps=1e-6;
int n,k,d;
int a[maxn];
int dp[maxn],pre[maxn];
bool ask(int l,int r){
if(r<l){
return 0;
}else if(l<=0){
return pre[r]>0;
}else{
return pre[r]-pre[l-1]>0;
}
}
signed main(){
scanf("%d%d%d",&n,&k,&d);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
int l=0;
dp[0]=1;
pre[0]=1;
for(int i=1;i<=n;i++){
while(a[i]-a[l]>d) l++;
dp[i]=ask(l-1,i-k);
pre[i]=pre[i-1]+dp[i];
}
printf(dp[n]?"YES\n":"NO\n");
return 0;
}
不摆烂了,写题