借书【二分】
题目描述
DilhaoDilhao一共有nn本教科书,每本教科书都有一个难度值,他每次出题的时候都会从其中挑两本教科书作为借鉴,如果这两本书的难度相差越大,DilhaoDilhao出的题就会越复杂,也就是说,一道题的复杂程度等于两本书难度差的绝对值。
这次轮到ldxxxldxxx出题啦,他想要管DilhaoDilhao借mm本书作为参考去出题,DilhaoDilhao想知道,如果ldxxxldxxx在DilhaoDilhao给出的mm本书里挑选难度相差最小的两本书出题,那么ldxxxldxxx出的题复杂程度最大是多少?
输入格式
第一行是nn和mm。
接下来的nn行,每行一个整数aiai表示第ii本书的难度。
输入格式
一个整数为ldxxxldxxx出的题复杂程度的最大值。
输入样例
6 3
5
7
1
17
13
10
输出样例
7
样例解释
DilhaoDilhao给了ldxxxldxxx难度为1,10,171,10,17的三本书,ldxxxldxxx挑选难度为1010和1717的两本书,出题复杂度为77;
如果DilhaoDilhao给出其他任何三本书,其中的两本书难度差的最小值都小于77,所以ldxxxldxxx出题最大的复杂程度为77。
数据说明
对于 30%30%的数据: 2≤n≤202≤n≤20;
对于 60%60%的数据: 2≤n≤10002≤n≤1000;
对于 100%100%的数据: 2≤n≤1000002≤n≤100000, 2≤m≤n2≤m≤n, 0≤ai≤10000000000≤ai≤1000000000。
思路分析
- 题目很好理解,一堆书中给你m本书,选出这m本书中两本书难度差最小的值作为出题的复杂程度,最后输出最大复杂程度,显然是一道最小值最大化的问题,就需要用到二分
二分从哪里入手
- 首先可以明确的是这题要对差值处理,考虑到我们要选m本中的最小差值,那么我们完全可以将原数组排序后处理为差分数组,然后两个数的差值从前往后加即可
- 二分过程:
- 最大的最小差值为边界,然后判断右边界(显然右边界最大)是否成立,成立即为最优答案,否则再判断mid,进行区间缩小
- 判断条件:我们只需要看以该值作为最小差值是否能选出m个数即可(即m-1个差值)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int maxn=1e5+5;
int n,m,a[maxn],cf[maxn];
int Max=0;
void Init(){
n = read(),m = read();
for(int i=1;i<=n;i++){
a[i] = read();
Max=max(Max,a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<n;i++){
cf[i]=a[i+1]-a[i];//cf差分数组
}
}
bool check(int x){ //x为二分过程中枚举的差值
int cnt=0,ch=0;//ch当前的最大差值
for(int i=1;i<n;i++){
ch+=cf[i];
if(ch>=x){//找到一对差值大于x
cnt++,ch=0;//从下个位置找下一对
}
}
if(cnt>=m-1)return true; //能够找出m-1个差值
return false;
}
int main(){
n = read(),m = read();
for(int i=1;i<=n;i++){
a[i] = read();
Max=max(Max,a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<n;i++){
cf[i]=a[i+1]-a[i];//cf差分数组
}
int l=0,r=Max;
while(l<=r){
if(r-l==1){ //区间不能再缩小
if(check(r)==true) //右边界最大,判断是否可以作为答案
l=r;
break;
}
int mid=(l+r)/2;
if(check(mid)==true) //向右缩小空间,继续寻找更优解
l=mid;
else r=mid; //中间值太大,向右缩小区间
}
printf("%d
",l);//左边界最小,一定符合答案
return 0;
}
发量成功减1%