• 整数二分的正确打开方式


    参考: 算法竞赛 , 这篇$Blog$

    感觉二分一直迷迷糊糊,终于要来写一篇小结辣

     总的来说有两种写法:

      1.记录答案

      2.不记录答案

     细分有三种:

      1.记录答案(左右边界哪个是答案都差不多)

      2.不记录答案且找最小的合法解

      3.不记录答案且找最大的合法解(最易错的!!)

    下面就来具体说说细分的三种

     1.记录答案

    //找到最大的合法解

    while
    (l<=r) { int mid=(l+r)>>1; if(check(mid))ans=mid,l=mid+1; else r=mid-1; } printf("%d ",ans);
    //找到最小的合法解

    while
    (l<=r) { int mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } printf("%d ",ans);

     2.不记录答案且找最小的合法解

    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    printf("%d
    ",l);

     3.不记录答案且找最大的合法解

    $Attention!$这里一定是$mid=(l+r+1)>>1$

    考虑这样一种情况:$r=l+1,mid=(l+r)>>1=l$,$l$合法,$l=mid=l$,于是陷入死循环

    while(l<r)
    {
        int mid=(l+r+1)>>1; //!Attention!
        if(check(mid))l=mid;
        else r=mid-1;
    }
    printf("%d
    ",l);

    注意点与拓展

    1.不同的形式采取相应的$mid$取法

    2.采取$>>1$而不是$/2$.这是因为右移运算是向下取整,而整数除法是向$0$取整,在二分值域包含负数时出错.

    3.(对于后面两种做法而言)处理二分中的无解情况: 把最初的二分区间$[1,n]$扩展成$[0,n+1]$,如果二分终止后停留在扩展结点上则无解

    讲了这么多我觉得还是第一种做法最好了,考虑的要少很多: )

    但是算法竞赛上就第一种没讲???

    光伴随的阴影
  • 相关阅读:
    js表单验证
    i利用图片按钮 和 input type="image" 为背景提交表单
    php 时间转换
    select 响应时间 js
    浏览器兼容
    选修课程的级联。
    时间显示的位置
    广告飘动
    C++--引用
    ubuntu中可以ping通IP地址但是ping不通域名的问题(www.baidu.com)
  • 原文地址:https://www.cnblogs.com/forward777/p/11274599.html
Copyright © 2020-2023  润新知