Luogu P2678 [NOIP2015 提高组] 跳石头
题目大意
给你一排 块石头,你可以移走
块石头(
,
),使得最小的两块石头之间的距离尽可能长。
输入格式
第一行包含三个整数 ,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。
接下来 行,每行一个整数,第
行的整数
(
),表示第
块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
输出格式
一个整数,即最短跳跃距离的最大值。
输入样例 #1
25 5 2
2
11
14
17
21
输出样例 #1
4
分析
我们可以换一个思路求解此题:从总距离$L$开始二分最小的最大距离 ,检测每个
需要搬走的石头数
,如果满足条件,则尝试更小的
,反之同理。
最后是代damn码:
#include<bits/stdc++.h>
#define int long long
#define MAXN 50005
#define endl '\n'
using namespace std;
int l,n,m,ans;
int a[MAXN];
bool cheak(int x){//目前查找的最小距离
int num=0,now=0;//要搬走的石头数,当前在的石头
for(int i=1;i<=n;i++){
if(a[i]-now<x)num++;//如果比当前x小,那么这种距离下要搬走的石头个数+1
else now=a[i];//跳到后一块石头
}
if(l-now<x)num++;//注意最后一块石头与总距离之间的距离也要小于x
return num<=m;//返回是否满足条件
}
signed main(){
cin>>l>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
int L=1,R=l;
while(L<R){
int mid=(L+R+1)>>1;
if(cheak(mid))ans=L=mid;//往右查询是否有最大值
else R=mid-1;//当前移走石头数大于M,只能往左查询
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号