一.使用二分需要满足两个条件:有界性和单调性
有界性:有界二分答案应在一个闭区间上进行;
单调性:问题的解分布在一个区间上,这里有很多不合法的解,也有很多合法的解.考虑所有合法(可行)解,目标是从这些可行解中找到一个最优的作为答案. 注意到最优解一定可行,但可行解不一定最优.假设整个序列具有单调性,一般地,若一个数为合法解,则对,都是合法解.若有一个数是非法解,则对,都是非法解.正是因为有单调性的存在,才使得每次舍弃解区间的一半或这种优化是正确的,因为保证舍弃的区间一定是非法解区间.
二.二分法模板(二分答案与二分查找)
二分法总是可以分成"求满足某条件的最大值"与"满足条件的最小值"两种情况,
其中"某条件"常常被封装成check()函数 判断当前解是否可行.
(1)整数域的二分
//寻找满足条件的最小值
int l=0,r=n,mid;
while (l<r)
{
mid=(l+r)/2;
if (check(mid))
r=mid;
else
l=mid+1;
}
//l即为所求
//寻找满足条件的最大值
int l=0,r=n,mid;
while (l<r)
{
mid=(l+r+1)/2;
if (check(mid))
l=mid;
else
r=mid-1;
}
//l即为所求
(2)实数域的二分
与整数域上的二分相比有变动,求mid时不在加1;else后也不再加1或减1;
三.二分法的应用:二分查找.查找有序序列中的元素,返回下标
1.如:求序列中第一个大于x的元素的下标,等价于寻找满足x<a[mid]的最小mid
求序列最后一个小于等于x的元素的下标,等价于寻找满足x>=a[mid]的最大mid
2.事实上,C++中封装了两个函数,可以方便地实现二分查找
upper_bound()返回第一个大于某元素的下标;等价于寻找满足a[mid]>x的最小值
lower_bound()返回第一个大于等于元素的下标;等价于寻找满足a[mid]>=x的最小值
如:
int tmp = upper_bound(a, a + 5, 7) - a;
/*data:
9
20 20 40 40 40 60 60 80 80
9
15 20 35 40 45 60 75 80 85*/
四.二分法的应用:二分答案.
如:最大(小)值最小(大)
来源:CSDN
作者:Vae_1118
链接:https://blog.csdn.net/Vae_1118/article/details/103843986