二分模板
浮点数二分
double l=0,r=x;
while(r-l>1e-(k+2))//保留k位小数
{
double mid=(l+r)/2;
if(check(mid))
{
l=mid;
}
else
{
r=mid;
}
}
整数二分
(区分
与
)
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;
}
二分查找
又叫折半查找,是一种用于快速查找的工具,也可以说是一种技巧与思想,要有二分的思想,很多算法和优化都用了二分。
例题Acwing789. 数的范围
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
while(m--)
{
int k;
cin>>k;
int l=0,r=n-1;
while(l<r)//寻找左边界
{
int mid=(l+r)/2;
if(a[mid]<k)
{
l=mid+1;
}
else{
r=mid;
}
}
if(a[l]==k)
{
cout<<l<<" ";
l=0,r=n-1;
while(l<r)//寻找右边界
{
int mid=(l+r+1)/2;
if(a[mid]>=k+1)
{
r=mid-1;
}
else{
l=mid;
}
}
cout<<l<<endl;
}
else{
cout<<"-1 -1"<<endl;
}
}
return 0;
}
相关题
2.P1873 [COCI 2011/2012 #5] EKO / 砍树
3. P1024 [NOIP2001 提高组] 一元三次方程求解
二分答案
解题的时候往往会考虑枚举答案然后检验枚举的值是否正确。若满足单调性,则满足使用二分法的条件。把这里的枚举换成二分,就变成了“二分答案”。
例题P1824 进击的奶牛
#include<iostream>
#include<cstdio>
#include<cstring>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<deque>
#include<vector>
#include<queue>
#include<map>
#include<stack>
#include<set>
//#define int long long int
using namespace std;
const int N=1e5+10;
int a[N];
int n,k;
int check(int x)
{
int num=1;//记录可放牛的数量
int s=a[1];//判断当前位置是否需要放牛
for(int i=1;i<=n;i++)
{
if(a[i]-s>=x)//当前位置与前一个确定位置距离超过最大值
{
num++;//在当前位置放一只牛
s=a[i];//更新位置
}
}
if(num>=k)//如果数量达到
{
return true;
}
else{
return false;
}
}
signed main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);//将牛棚排序
int l=0,r=(a[n]+a[1])/(k-1);//确定左右边界初始值
while(l<r)//二分模板
{
int mid=(l+r+1)>>1;
if(check(mid))
{
l=mid;
}
else{
r=mid-1;
}
}
cout<<l<<endl;
return 0;
}