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//查找首个大于给定值的元素的函数
二者均采用二分实现,所以调用前必须保证元素有序。