二分本质是用来查找满足某种性质的边界点
在给定区间内,能找到某种性质(check函数):
使得区间分为两部分
一部分满足,另外一部分不满足这种性质。
二分可以用来寻找这个性质的边界:满足某种性质的第一个元素;或者是满足某种性质的最后一个元素。
从而有两个不同模板
注意二分法一定能找到满足某种性质的边界点,但它不一定是你要找的目标,目标一不定在区间内,先写check函数,根据check函数更新区间,再判断用哪个模板。
二分模板一共有两个,分别适用于不同情况。
算法思路:
假设目标在闭区间[l,r]中,每次将区间长度缩小一半,当l=r时,我们就找到了目标值。
版本1
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid +1;,计算mid时不需要加1。
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
版本2
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l =mid;,此时为了防止死循环,计算mid时需要加1。
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
AcWing 789.数的范围
#includeusing namespace std; const int N=1e5+10; int q[N]; int n,m; int main() { cin>>n>>m; for(int i=0;i >q[i]; while(m--) { int k; cin>>k; int l=0,r=n-1; while(l >1; if(q[mid]>=k) r=mid; else l=mid+1; } if(q[l]!=k) cout<<-1<<' '<<-1< >1; if(q[mid]<=k) l=mid; else r=mid-1; } cout< AcWing 790.数的三次方根 #include浮点数的平方根using namespace std; int main() { double x; cin>>x; double l=-100,r=100;//根据题目范围 开三次方根 估计答案大概范围 while(r-l>1e-8) { double mid=(l+r)/2; if(mid*mid*mid>=x) r=mid; else l=mid; } printf("%.6lfn",l); return 0; } #includeusing namespace std; int main() { double x; cin>>x; double l=0,r; //一个浮点数开平方,答案绝对值一定大于等于0,但是右边界根据输入浮点数是否大于1确定 if(x>1) r=x; else r=1; while(r-l>1e-8)//经验: 保留6位小数 1e-8 4位 1e-6 多2 { double mid=(l+r)/2; if(mid*mid>=x) r=mid; else l=mid; } printf("%.6lfn",l); return 0; }



