洛谷P2678跳石头 二分答案

洛谷P2678跳石头 二分答案

这题的做法是:

二分答案

我在题解里学到,使用二分答案的情况是:单调+有界

这题就是求最小值里的最大值

多么!有趣!

说明什么呢

比如我们有三个石头,其中一个是起点,一个是终点,他们之间的距离为len

我们设一个变量mid=(0+len)>>1,

在这两个石头之间我们摆上了一块石头。

那么对于这三块石头,最短距离的最大值是谁呢?(设为min----max)

如果这个石头被放在了x==mid-1处,我们的min---max==mid-1

如果这个石头被放在了x==mid处,我们的min---max==mid

如果这个石头被放在了x==mid+1处,我们的min---max仍然为mid-1

所以,无论如何,我们的答案是小于mid的

接下来,就是围绕着这个mid展开

如果我们得到了一段距离,大于mid

那么这段肯定不在我们的“最短距离”这个范围内,所以要离开这地方

如果这个值它在这个范围里,那么我们就考虑把这个我们这个石头移掉,扩大我们“最短距离”的“最大值”

比如A B C D E F G H I,我们知道了AB的距离小于mid,现在把B给移掉,移掉的石头数++,现在最短距离的范围仍然在mid里面

然后发现AC的距离仍然小于mid,那么把C也给移掉,因为AC符合”最短距离”这个范围,并且我们想把这个范围给扩大,所以把它移掉试试,

也就是说,我们遇到比mid小的,就想办法把那块石头给移走,再去找个最大值

然后再去试D,E ,F,······

试过一趟之后,如果石头移得个数超过了,则在左边重新找

如果还没移满,就在左边继续找找看,继续找最优解

假设,初始的mid是len/2,这是三个石头一定会满足的,最短距离的最大值一定小于这个mid

然后我们最后的答案就会在0~mid中得出

然后接下来要做的就是不断地缩小范围,删去石头,直到我们得到一个在0~mid之间的确定值ans

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 #define sys system("pause");
 5 inline int read(){
 6     int x=0,f=1;char c=getchar();
 7     while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
 8     while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 9     return x*f;
10 }
11 int a[50020];
12 int len, n, m, ans, l, r, now, tot;
13 void init(){
14     len = read(), n = read(), m = read();
15     for (int i = 1; i <= n;i++)
16         a[i] = read();
17 }
18 int32_t main(){
19     init();
20     r = len;
21     while(l<=r){
22         int mid = (l+r) >> 1;
23         now = 0, tot = 0;
24         for (int i = 1; i <= n;i++)
25             a[i] - a[now] < mid ? tot++ : now = i;
26         tot <= m ? (ans = mid, l = mid + 1) : (r = mid - 1);
27     }
28     printf("%lld", ans);
29     sys
30     return 0;
31 }

结束~

 

上一篇:P2678 跳石头


下一篇:P2678 跳石头