二分

二分

条件:往往要先给要查询的那组数据进行排序

单调性

例子
  1. 比如砍伐树的高度与木材总长有关系。砍伐越矮,木材总长越长。

  2. 比如木材的长度与能切割成的小段关系,木材长度越短,小段越多,木材长过一定长度能切出的等长小段就可能减少,但不可能增加。(P2240)

  3. 当按照贪心的方式移走石块时:移动的石子数与最小最大距离呈现单调递增关系(P2678)

分析
  1. image-20210804160533497(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

有界

作用:

二分可以在一堆里面查一个索引

抽象:二分通过条件控制,找到一个符合条件的最优值临界值

  1. 比如在n个学校录取分数线里面找与学生分数差值绝对值最小的两个值,查询学生分数线的位置

  2. 控制搜索区域使达到最优值

//目标区间左边界
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;//这
    }
}
posted @ 2021-10-21 22:15  多巴胺不耐受仿生人  阅读(94)  评论(0)    收藏  举报