洛谷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,最大值,mid,石头,短距离,移掉,我们 来源: https://www.cnblogs.com/guaguastandup/p/10457778.html