E. Pencils and Boxes 題解(雙指標+dp)
阿新 • • 發佈:2021-08-24
題目連結
題目大意
你有 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; }