• 写正确的整数二分 |oyxBlog


    二分

    第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间。
    ——不知道哪里看的

    整数二分

    yxc二分模板
    二分的本质是二段性不是单调性。


    当想找不满足性质的边界值(红色区域的右边界值)

    1. 找中间值 mid = (l+r+1)/2
    2. if(check(mid))等于true或者是false
      check(m)是检查m是在不满足性质的区间(检查是不是在红色区间)
    3. 更新l或者r

    二分左区间的右端点


    当想找满足性质的边界值(绿色区域的左边界值)

    1. 找中间值 mid = (l+r)/2
    2. if(check(mid))等于true或者是false
      check(m)是检查m是在满足性质的区间(检查是不是在绿色区间)
    3. 更新l或者r

    二分右区间的左端点


    归结上面的两种二分方法,步骤为:

    1. 先写一个check函数
    2. 判定在check的情况下(true和false的情况下),如何更新区间。
    3. 在check(m)==true的分支下是:
      1. l=mid的情况,中间点的更新方式是m=(l+r+1)/2
      2. r=mid的情况,中间点的更新方式是m=(l+r)/2

    这种方法保证了:

    1. 最后的l==r
    2. 搜索到达的答案是闭区间的,即a[l]是满足check()条件的。

    模板

    acwing 789

    //#define judge
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 10;
    int n, q, k;
    int a[maxn];
    int main() {
    #ifndef judge
      freopen("in.txt", "r", stdin);
      freopen("out.txt", "w", stdout);
    #endif
      scanf("%d%d", &n, &q);
      for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
      }
      for (int i = 0; i < q; i++) {
        scanf("%d", &k);
        int l = 0, r = n - 1;
        while (l < r) {
          int mid = l + r >> 1;
          if (a[mid] >= k) {
            r = mid;  //第二种情况 找绿色区间的左端点
          } else {
            l = mid + 1;
          }
        }
        if (a[l] != k) {
          printf("-1 -1
    ");
        } else {
          printf("%d ", l);
          l = 0, r = n - 1;
          while (l < r) {
            int mid = l + r + 1 >> 1;
            if (a[mid] <= k) {//第一种情况 找红色区间的右端点
              l = mid;
            } else {
              r = mid - 1;
            }
          }
          printf("%d
    ",l);
        }
      }
      return 0;
    }
    

    一些其他细节

    为什么需要+1?
    原因是如果不加上1,那么mid得到的是下取整的数,那么有可能[m,r]更新过后m会一直等于m(m+1==r的情况)会陷入死循环。

  • 相关阅读:
    sed点滴
    JS中使用window.open("url?param="+paramvalue)传递参数出现乱码
    java算法之插入排序法
    NodeJS中的事件模块EventEmitter
    转载: 通过Object.prototype.toString 精确判断对象的类型
    CommonJS的模块规范
    Windows Store App之文件选择器、文件保存器和文件夹选择器
    vue日期格式化
    Linux下安装Apache
    ubuntu 安装 ES 以及集群的搭建
  • 原文地址:https://www.cnblogs.com/adameta/p/12269341.html
Copyright © 2020-2023  润新知