题解 P1824 【进击的奶牛】
非常经典的一道二分答案模板题
什么是二分答案?简单地说,就是和二分查找相似,二分每个答案,然后对这个答案进行求证,看是否满足条件,然后再次进行左右区间查找,知道二分到单个点上
因为我太弱了,可能说的话有些逻辑错误或者表达不清qwq
这一题,我们二分答案找每个牛棚之间的最大距离。
先上代码:
#include <bits/stdc++.h>
using namespace std;
int n,m;
int ans=-1;
int a[1000005];
bool check(int x){ //答案是否满足,满足返回1,反之返回0
int now = 1, num = 1;
for (int i = 2; i <= n; i++){
if (a[i]-a[now]>=x){
now=i;
num++;
}
}
return num>=m;
}
void merge(int l,int r){
if(r-l<0) return; //边界
int mid=l+(r-l>>1); //这样处理防止溢出
if(check(mid)){ //如果满足,我们记录当前最大值,然后往左区间寻找答案
merge(mid+1,r);
ans=max(ans,mid);
}
else{ //如果不满足,就往右区间寻找
merge(l,mid-1);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1); //注意,要排序处理。
merge(1,(2<<30));
printf("%d",ans);
}
二分答案的merge()都差不多,主要是check()
这里细讲本题check:
我们假设最大距离是x,将题目意思转变一下,就变成了这样:
在n个数中选取m个数,它们两两之间的距离大于等于x。
因为我们的数列是满足单调性质的,所以我们可以从第一个数往后找,看看有几个数满足a[i]-a[i-1]<=x;
如果数量大于m,则满足条件,反之亦然.
bool check(int x){
int now = 1, num = 1;
for (int i = 2; i <= n; i++){
if (a[i]-a[now]>=x){
now=i;
num++;
}
}
return num>=m;
}
几个要强调的:
- 我是蒟蒻,欢迎大家指出错误和不足
- 二分的过程我就不讲了,和二分答案是差不多的
- 身体原因要离开OI一段时间,希望大家能点赞支持
- 2019 CSP rp++!