POJ 3258-River Hopscotch(二分答案)
River Hopscotch
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 25633 Accepted: 10556
Description
Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).
To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.
Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ M ≤ N).
FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.
Input
Line 1: Three space-separated integers: L, N, and M
Lines 2…N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.
Output
Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks
Sample Input
25 5 2
2
14
11
21
17
Sample Output
4
<WFU常规赛(二)>B题
每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一块岩石跳到另一块岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和距离起点 L 远的终点各有一块岩石 (1 ≤ L ≤ 10^9)。在起点和终点之间,有 N 块岩石 (0 ≤ N ≤ 50000),每块岩石与起点的距离分别为 Di (0 < Di < L)。
在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一块岩石跳到另一块岩石。当然,实力不济的奶牛无法抵达终点,在河中间就退出比赛了。
农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长,跳到终点的距离不计入。他可以移走除起点和终点外的至多 M 块岩石 (0 ≤ M ≤ N)。
请帮助农夫约翰确定:移走这些岩石后,最短跳跃距离的最大值是多少?
输入
第 1 行包含以单个空格分隔的三个整数 L, N, M。
第 2 到 N + 1 行,每行一个整数,表示每个岩石与起点的距离。不会有两个岩石出现在同一个位置。
输出
输出一个整数,即最短跳跃距离的最大值。
示例输入
25 5 2
2
14
11
21
17
示例输出
4
提示
在移除位于 2 和 14 的两块岩石之后,最短跳跃距离达到了最大值 4 (从 17 到 21,或从 21 到 25)。
解题思路:这道题是一道二分答案的题,题意有点难理解,求的是最短距离的最大值,那我们可以二分这个最大值,看看最后移走的岩石是不是小于等于m块(至多移走m块岩石),值得注意的是,这里起点0和终点L也要放在数组中,显然这个下界是0,上界是L,定义countseg函数来统计符合条件的石头,如果这个数量大于m(为什么不能大于等于,因为我们最后求的是小于等于 m 块岩石,我们要维持一个合法的边界,大于m不合法,小于等于m合法,所以必须大于m,最后输出 l 的值,就是最接近m的答案),则调小 Mid,反之调大,输出 l 的值就可以。贴ac代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const ll _max=0x3f3f3f3f3f3f3f3f;
int a[N],n,m,final;
int main()
{
int countseg(ll);
while(cin>>final>>n>>m)
{
for(int i=0;i<n;i++)
cin>>a[i];
a[n]=final;
sort(a,a+n+1);
ll l=0,r=final+1;
while(l<r-1)
{
ll mid=(l+r)>>1;
if(countseg(mid)>m)
r=mid;
else
l=mid;
}
cout<<l<<endl;
}
return 0;
}
int countseg(ll mid)
{
ll s=0,ans=0;
for(int i=0;i<=n;i++)
if(a[i]-s<mid)
ans++;
else
s=a[i];
return ans;
}
对countseg函数的解释:看符合距离比mid小的石头有几块,为什么不用小于等于mid,因为等于mid的时候就已经不合法了,因为我们要返回的是小,不是不超过,说明大于等于的时候不符合条件,最后返回岩石的数量。
int countseg(ll mid)
{
ll s=0,ans=0;//s从起点0处开始
for(int i=0;i<=n;i++)
if(a[i]-s<mid)//必须小于
ans++;
else
s=a[i];
return ans;
}