二分模板
整数二分模板
直接上一道题
求一个数所在的区间范围,不存在则输出 -1 -1
输入
6 3
1 2 2 3 3 4
3
4
5
输出
3 4
5 5
-1 -1
这里需要两个二分,一个找到最小的x,一个找到最大的x
- 主要差异在while循环里
bs1是找到符合要求的最小的下标
int bs1(int x){
int l = 0,r = n - 1,mid;
while(l < r){
mid = (l+r) >> 1;
if(a[mid] >= x)r = mid;
else l = mid + 1;
}
return l;
}
bs2是找到符合要求的最大的下标
int bs2(int x){
int l = 0,r = n-1,mid;
while(l < r){
mid = (l + r + 1) >> 1;
if(a[mid] <= x) l = mid;
else r = mid - 1;
}
return l;
}
浮点数模板
直接上一道题
求一个数的三次方根,小数点后保留6位数
#include <iostream>
#include <cmath>
using namespace std;
double n,esp = 1e-8;
int main(){
cin >> n;
double l = min(-n,n),r = max(-n,n);
// 左区间 < 右区间, n可能是负数
double mid;
while(r - l > esp){
mid = (l + r) / 2;
if(mid *mid *mid >= n)r = mid;
else l = mid;
}
printf("%.6lf",l);
return 0;
}
其实这样是不对的,需要考虑 -1~1 这个区间。
比如 0.001的三次方根是0.1
因为我们给的右边界是n,同时默认了n大于最后的结果。
但是在0~1这样的区间里,数字n的2次方、3次方都不会大于n本身,
所以二分只能在一个小区间里找到最接近结果的那个数,就是0.001
正确的写法是判断n的大小,如果是在-1~1这个区间里的话:
double l = -1,r = 1;