我们在二分的时候需要满足步骤:
一.先确定一个区间,使得目标值一定在一个区间内。
二.q找一个性质,性质需要满足以下两点:
1.性质需要满足二段性,即一个点前半段不满足·要求,后半段满足要求。
2.答案是2段性的分界点。
二分的2个模板
第一种,找大于等于X的最小数
比如对于下面这种情况(X小于mid) :
那么[X,mid]之间肯定全部都是大于X的值,那么答案(大于等于X的第一个数),肯定在[X,mid]之间,所以我们需要缩小右区间,。
为什么不是r=mid-1呢?因为[X,mid]都是可能包含答案的。
那么假设X大于mid呢?如图:
如图所示,答案(大于等于x的第一个数)肯定在[X,R]之间。
那么左半边肯定没有我们的答案,我们需要缩小左端点:
l=mid+1
为什么是L=mid+1,而不是L=mid呢? 因为mid肯定不包括答案。
对于这种情况,我们的模板就是
while(l<r)
{
int mid=l+r>1;
if(check()) r=mid;
else l=mid+1;
}
第二种情况,找小于等于X的第一个数
如上图所示,答案(小于等于X的第一个数) 肯定在左半区间,所以我们需要缩小右端点:
r=mid-1 (因为mid不包括答案)
假设mid<x:
那么答案肯定在[l,x]之间,所以需要缩小左端点:
l=mid (如图所示,mid可能包含答案)
对于第二种情况,模板如下:
while(l<r)
{
int mid=l+r+1>>1;
if(check()) l=mid
else r=mid-1;
}