二分

1.解释

其实这个东西吧,是分治的分支

优点:时间复杂度低,十分简单,方便写,适用绝大多数题目

缺点:总有人眼瞎写错()

2.步骤

1.在序列中确定中间数

2.判断这数是不是,\(<\)的话去左边找,否则去右边找

3.重复步骤直到中间数是要求的数字

3.例题

题目:洛谷 P1873

方法:朴素算法查找肯定超时,所以二分答案,check检查可行性,find二分

核心代码:

    bool check(int k) {  // 检查可行性,k 为锯片高度
  long long sum = 0;
  for (int i = 1; i <= n; i++)       // 检查每一棵树
    if (a[i] > k)                    // 如果树高于锯片高度
      sum += (long long)(a[i] - k);  // 累加树木长度
  return sum >= m;                   // 如果满足最少长度代表可行
}

int find() {
  int l = 1, r = 1e9 + 1;   // 因为是左闭右开的,所以 10^9 要加 1
  while (l + 1 < r) {       // 如果两点不相邻
    int mid = (l + r) / 2;  // 取中间值
    if (check(mid))         // 如果可行
      l = mid;              // 升高锯片高度
    else
      r = mid;  // 否则降低锯片高度
  }
  return l;  // 返回左边值

4.技巧

分清左闭右开和左开右闭!!!

5.拓展

这里介绍二分法常用的两个函数

std::lower_bound //不小于给定值的元素的函数,注意不小于 !!
std::upper_bound//查找首个大于给定值的元素的函数

二者均采用二分实现,所以调用前必须保证元素有序。

posted @ 2025-01-16 17:07  March7thDev  阅读(33)  评论(0)    收藏  举报