题目
分析
二分+贪心
首先我们把这个问题简化一下,改成给你范围r,问最少用几次魔法。那么就变成了简单的贪心问题,我们只需要在遍历数组时,尽可能地覆盖最多的人。具体就是先排序,然后从左到右遍历时,维护当前未被覆盖的最左的人i的位置,那么下一个覆盖范围就是[a[i],a[i]+r-1],以此类推。这里不理解qq问吧,讲不明白。
现在我们二分枚举这个范围r,对于每一个r,贪心的计算需要的区间个数,二分出区间个数小于等于k的最多的区间个数,对应的是最小的r。
代码
///女装,或者WA 二分+贪心
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int aa[100010];
int n, k;
bool check(ll x)
{
int cnt=0;
ll pre=-1;
for(int i=0;i<n;i++){
if(aa[i]<=pre)continue;
pre = x+aa[i]-1;
cnt++;
}
if(cnt<=k)return true;
return false;
}
int main()
{
int T;
// freopen("A2.in","r",stdin);
// freopen("A2.out","w",stdout);
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
ll sum=0;
for(int i=0;i<n;i++)scanf("%d",&aa[i]),sum+=aa[i];
sort(aa,aa+n);
ll l=0, r=sum, mid ,ans;
while(l<=r){
mid = (l+r)>>1;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}