二分
二分
条件:往往要先给要查询的那组数据进行排序,
单调性
例子
-
比如砍伐树的高度与木材总长有关系。砍伐越矮,木材总长越长。
-
比如木材的长度与能切割成的小段关系,木材长度越短,小段越多,木材长过一定长度能切出的等长小段就可能减少,但不可能增加。(P2240)
-
当按照贪心的方式移走石块时:移动的石子数与最小最大距离呈现单调递增关系(P2678)
分析
(P2678) 二分法在搜索范围(最小值d的数值大小范围)内的数据可分为可行解与不可行解,由于本题移走石块数k与最小距离d具有单调递增关系(以贪心方式移动),即k越大d越大,设最小最大值为x,解的是否可行取决于k是否等于m,若等于则可行,若不等于则不可行①当d<x时,若k==m(至多已走的的石块数m个)则d为可行解,否则为不可行解,②当x<d时,d为不可行解。因为k与d的大小单调递增,所以当d处1.第一区、第二区时,由于k<=m值,求这时mid仍可尝试增大,有递增关系但增大后k不一定超过m,我们要求d的最大值,于是我们将查询区域向右移动,令l=mid,d的查询区间增大。2.反之k>m值,不可行,要减小mid的值,令查询区间左移r=mid-1
有界
作用:
二分可以在一堆里面查一个索引
抽象:二分通过条件控制,找到一个符合条件的最优值(临界值)
-
比如在n个学校录取分数线里面找与学生分数差值绝对值最小的两个值,查询学生分数线的位置
-
控制搜索区域使达到最优值
//目标区间左边界
int bs(int x, int l = 1, int r = n)
{
while (l < r)
{
int mid = l + r >> 1;
if (a[mid] >= x)
r = mid; //记忆技巧:r指针从右往左移动,因此是得到左边界
else
l = mid + 1;
}
}
//目标区间右边界
int bs(int x, int l = 1, int r = n)
{
while (l < r)//按照下面的语句,r==l时跳出循环,且不会产生l>r的情况的(因为r=mid-1,l=mid,向下取整,查询区间在l,r内)
{
int mid = l + r +1>> 1;//防止当r==l+1又满足a[mid]<=x时死循环
if (a[mid] <= x)//取决于答案要求的左右边界 (<= >=)
l = mid;//这是在控制查询区间
else
r = mid - 1;//这
}
}
本文来自博客园,作者:多巴胺不耐受仿生人,转载请注明原文链接:https://www.cnblogs.com/VoidCoderTF/articles/15435486.html

浙公网安备 33010602011771号