前言
二分搜素
常见于最()的 最 ()。
一、二分是什么
减少搜索次数
二、使用步骤
1.格式
int l= ;
int r= ;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]==b[i])
{
if(a[mid-1]!=b[i]&&mid>1)
{ans=mid;break; }
if(mid==1)
{
ans=mid;break;
}
}
if(a[mid]<b[i])l=mid+1;
else r=mid-1;
}
2.读入数据
快读
inline int read()//inline 内联 可以加快速度
{
register int s=0,t=1;//register 也是加快速度的
register char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
{
t=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return t*s;
三、
例题 1
【深基13.例1】查找
题解
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
scanf("%d",&n);//scanf 比cin快
scanf("%d",&m);
int a[n+1],b[m+1];
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
}
for(int i=1;i<=m;i++)
{
int l=1,r=n,pos=-1;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]==b[i])
{
if(a[mid-1]!=b[i]&&mid>1)
{pos=mid;break; }
if(mid==1)
{
pos=mid;break;
}
}
if(a[mid]<b[i])l=mid+1;
else r=mid-1;
}
printf("%d ",pos);
}
return 0;
}
例题2
P1824 进击的奶牛
#include<iostream>
#include<algorithm>
using namespace std;
int n,c;
int a[100010];
int check(int mid)//第一头牛放置在第一个隔间中 所以从第二头牛开始判定距离是否符合条件
{
int k=1;
int xianzai=a[1];
for(int i=2;i<=n;i++)
{
{if(a[i]-xianzai>=mid){xianzai=a[i];k++;}}//若第i个隔间符合这个距离 将下一头牛放置在该隔间中
}
return k;//得到这个距离能放置多少头牛
}
int main()
{
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
int l=1,r=a[n]-a[1],ans;//l为距离下界 r为距离上界;运用二分从中间值开始遍历
while(l<=r)
{
int mid=(r+l)/2;
if(check(mid)>=c) {ans=mid,l=mid+1; }//判断能否将牛全都放下 若能则下界增
else r=mid-1;//若不能 则上界减
}
printf("%d",ans);
return 0;
}
例题3
P2678 [NOIP2015 提高组] 跳石头
思路
用mid代表跳跃距离,用check 检查该mid在该数组去掉几块石头,若下一块石头到现在这块石头的距离大于该mid,则删掉这下一块石头,直到下一块石头到现在这块石头的距离大于该mid。更新现在这块石头为这下一块石头,直到所有石头全部判断完毕,得到要删掉的石头数,判断是否满足题意。若满足 则距离下界增加,若不满足 则上界减少,直到上下界重合。
#include <iostream>
using namespace std;
int n,m,L,daan;
int a[50010];
int check(int x)
{
int now=0,nm=0;
for(int i=1;i<=n+1;i++){
if(a[i]-now<x){
nm++;
}
else{now=a[i];}
}
if(nm<=m)
return 1;
return 0;
}
int main()
{
scanf("%d%d%d",&L,&n,&m);
for(int i=1;i<=n;i++){scanf("%d",&a[i]); }
a[n+1]=L;
int l=1,r=L;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
l=mid+1;
daan=mid;
}
else{ r=mid-1; }
}
printf("%d",daan);
return 0;
}
总结
找到二分的对象进行判断,直到上下界重合