有单调性一定可以二分,没有单调性也可以二分
整数二分步骤:
1、找一个区间[L,R],使得答案一定在区间中
2、找一个判断条件、使得该判断条件具有二段性,并且答案一定是该二段性的分界点
3、分析中点M在该判断条件下是否成立,如果成立,考虑答案在哪个区间,如果不成立,考虑答案在哪个区间
4、如果更新方式写的是R=Mid,则不用做任何处理;如果更新方式写的是L=Mid,则需要在计算Mid时加上1
第一类二分模板:
ans是在绿色区域的右端点
将[L,R]分成[L,M-1],[M,R]
if M是绿色的,说明ans仍然在[M,R]
else 说明ans在[L,M-1]
分析极限情况:
L=R-1
M=(L+R+1)/2=R
R=M-1=R-1=L
核心代码:
while(L<R){
int mid=(L+R+1)/2;
if(mid为绿) L=mid;
else R=mid-1;
}
如何判断是否是第一类模板:
如果L=M,说明需要在取中点的时候+1,即(L+R+1)/2
第二类二分模板:
ans是在蓝色区域的左端点
将[L,R]分成[L,M],[M+1,R]
if M是蓝色的,说明ans在[L,M]
else 说明ans在[M+1,R]
分析极限情况:
L=R-1
M=(L+R)/2=L
L=M+1=L+1=R
核心代码:
while(L<R){
int mid=(L+R)/2;
if(mid为蓝) R=mid;
else L=mid+1;
}
如何判断是否是第一类模板:
如果R=M,说明不需要在取中点的时候+1,即(L+R)/2
实数二分:
实数二分模板:
将区间[L,R]划分为[L,M],[M,R]
if ans在坐去左区间[M,R],L=M
else if ans在右区间[L,M] R=M
while(L-R>1e-6){
double mid=(L+R)/2;
if(mid为左区间) R=mid;
else L=mid;
}