整数二分实质上是找到一个区间的左半部分满足一个性质,右半部分满足另外一个性质,二分查找这两个区间的边界
1.如果我们找的是左区间右边界,check(mid)是确定mid符不符合左区间条件,那么如果符合的话答案一定在mid右边,且mid有可能是答案
所以更新区间是[mid,r]操作为l=mid,如果不符合那么答案一定在mid左边且mid不可能是答案,所以更新区间为[l,mid-1],操作为r=mid-1
这种r=mid-1或l=mid的情况需要mid=l+r+1>>1
需要+1的原因:
如果二分到l=r-1的情况,那么这个时候不+1,mid=(l+r)/2=l,更新区间为[mid,r]或者[l,mid-1],实际上是[l,r],[l,l-1],会出现死循环或者RE
所以+1,判断[l,l]和[r,r]哪个是边界
2.如果我们找的是右区间的左边界,check(mid)确定的是mid符不符合右区间的条件,那么如果符合的话答案一定在mid左边,且mid有可能是答案
所以更新区间是[l,mid]操作为r=mid,如果不符合那么答案一定在mid右边且mid不可能是答案,所以更新区间为[mid+1,r],操作为l=mid+1
这种r=mid或l=mid+1的情况需要mid=l+r>>1
=======================================
所以看到-1就给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;
}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;
}
实数二分
定义一个eps精度为1e(-n-2),n为题目规定的精度
while(r-l[HTML_REMOVED]>1;
if(check(mid))r=mid;
else l=mid;
}
也可以直接循环100次
for(int i=1;i<=100;i++)
{
double mid=l+r>>1;
if(check(mid))r=mid;
else l=mid;
}