网上看到一个有意思的二分,这里分享一下
// 出处 https://www.bilibili.com/video/BV1d54y1q7k7
假设二分区域为 [0, n - 1]
//
int l = -1, r = n; // l 和 r 在区域【0,n - 1】外
while (l + 1 != r)
{
int mid = l + r >> 1;
if (isInBlue(mid)) l = mid;
else r = mid;
}
// 当 l + 1 == r 的时候退出while 循环
// 退出循环之后需要判断一下边界问题
// 1. 当 l == -1 的时候,说明没有蓝色区域,根据具体的题目进行判断,避免出现越界的情况
// 2. 当 r == n 的时候,说明没有红色区域,根据具体的题目进行判断,避免出现越界的情况
// 退出 循环之后再根据具体的情况选择使用l 还是使用 r
$\color{#0000FF}{例子}$:[1,2,3,5,5,5,8,9]
- 找第一个 >= 5 的数 那么 (红色区域的左端点是r)
[ $\color{#0000FF}{1,2,3}$, $\color{#FF0000}{5,5,5,8,9}$],
思考一下[ $\color{#0000FF}{1,2,3,3,3,3,4,4}$] 这种情况 r 的值是多少,要如何处理
bool isInBlue(int mid)
{
return a[mid] < 5; // <5是蓝色区域,那么最后 r 的值会停在5的位置,返回r(退出while循环的时候需要处理一下r == n 的情况)
}
- 找第一个 > 5 的数 那么 (红色区域的左端点是r)
[ $\color{#0000FF}{1,2,3,5,5,5}$, $\color{#FF0000}{8,9}$]
bool isInBlue(int mid)
{
return a[mid] <= 5; // <=5是蓝色区域,那么最后 r 的值会停在8的位置,返回r(退出while循环的时候需要处理一下r == n 的情况)
}
- 找最后一个 < 5 的数 那么(蓝色区域的右端点是l)
[ $\color{#0000FF}{1,2,3}$, $\color{#FF0000}{5,5,5,8,9}$]
bool isInBlue(int mid)
{
return a[mid] < 5; // <5是蓝色区域,那么最后 r 的值会停在5的位置,返回l(退出while循环的时候需要处理一下r == n 的情况)
}
- 找最后一个 <= 5 的数 那么(蓝色区域的右端点是l)
[ $\color{#0000FF}{1,2,3,5,5,5}$, $\color{#FF0000}{8,9}$]
bool isInBlue(int mid)
{
return a[mid] < 5; // <5是蓝色区域,那么最后 r 的值会停在5的位置,返回l(退出while循环的时候需要处理一下r == n 的情况)
}
这个二分怎么了嘛
我入门的时候的二分都这样写的/emm