week 2 二分

前言

二分搜素

常见于最()的 最 ()。

一、二分是什么

减少搜索次数

二、使用步骤

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;
}


总结

找到二分的对象进行判断,直到上下界重合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值