二分
二分模板
1.
while (l < r)
{
int mid = l + r >> 1; //(l+r)/2
if (check(mid))
r = mid; // check()判断mid是否满足性质
else
l = mid + 1;
}
2.
while (l < r)
{
int mid = l + r + 1 >> 1; //(l+r+1)/2
if (check(mid))
l = mid;
else
r = mid - 1;
}
3. 浮点二分
while(r-l>1e-5) //需要一个精度保证
{
double mid = (l+r)/2;
if(check(mid)) l=mid; //或r=mid;
else r=mid; //或l=mid;
}
看个例题
题解
#include<iostream>
using namespace std;
const int N=1000010;
int a[N],x,q,n;
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>a[i];
while(q--)
{
cin>>x;
int l=1,r=n; //左右边界
while(l<r) //因为是找第一次出现的位置,那就是尽量往左来,就用模板1
{
int mid=l+r>>1;
if(a[mid]>=x) r=mid; //判断条件,如果值大于等于目标值,说明在目标值右边,尽量往左来
else l=mid+1;
}
if(a[l]!=x)//如果找不到这个值
{
cout<<-1<<" ";
continue;
}
cout<<l<<" ";
}
return 0;
}
总结:二分法最重要的两个点,就是循环条件和后续的区间赋值问题