双十二,那就刷几个二分罢~

嘿嘿,跟对师傅很重要~这里参考下y总的二分模板

package 二分;

public class 模板一 {
  public static void main(String[] args) {
	int []a= {0,1,3,5,5,5,7};
	int l=1;
	int r=7;
	int ta=5;
	
	//*****************************************************
	while(l<r)//模版1
	{
		int mid=l+r>>1;
	if(a[mid]>=ta) r=mid;
	else l=mid+1;//判断:在目标值的右边,满足,往左来
	}
	System.out.println(l);
	//******************************************************
	 l=1;
	 r=7;
	 ta=5;
	while(l<r)
	{
		int mid=l+r+1>>1;
	if(a[mid]<=ta) l=mid;//判断:在目标值的左边,满足,往右去
	else r=mid-1;
	}
	System.out.println(l);
	}
}

模版1,查找最左边

模版2 ,查找最右边

上面代码的输出是3 5

即为查找的第一个5和最后一个5

那我们就开始砍题了

模版题,因为查找 第一次出现,直接套用模版1

package 二分;

import java.util.Scanner;

public class 洛谷查找 {
	 static int []a=new int [1000005];
	  public static void main(String[] args) {

		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int m=sc.nextInt();
		for(int i=1;i<=n;i++)
		{
			a[i]=sc.nextInt();
		}
		for(int i=0;i<m;i++)
		{
			int k=sc.nextInt();
			int l=1;int r=n;
			while(l<r)
			{
				int mid=l+r>>1;
			//if(a[mid]==k) {System.out.println(mid); break;}
			if(a[mid]>=k)r=mid;
			else  l=mid+1;
			}
			
			if(a[l]!=k){ //如果找不到这个值 
				System.out.print(-1+" ");
				continue;
			}
			System.out.print(l+" ");
			//if(l==r) System.out.println(-1);
		}
	}

}

一个需要思考一下的二分

二分先排序不解释

我们可以先遍历一遍,找b,再用模版一通过b+c找a,如果能找到a,再用模版二找最后一个a,俩a下标距离就是数对个数,以此类推。。

package 二分;

import java.util.Arrays;
import java.util.Scanner;

public class a减bproblrm {
 public static void main(String[] args) {
	 long a[]=new long  [200005];
	 int st=0;long cnt=0;
	Scanner sc=new Scanner(System.in);
	int n=sc.nextInt();
	long c=sc.nextLong();
	for(int i=1;i<=n;i++)
	{
		a[i]=sc.nextLong();
	}
	Arrays.sort(a,1,1+n);
	for(int i=1;i<n;i++)
	{
		int l=0;int r=n;
		while(l<r)
		{
			int mid=l+r>>1;
		
		if(a[mid]-a[i]>=c)r=mid;
		else  l=mid+1;
		}
		if(a[l]-a[i]==c) st=l;
		else continue;
	
	 l=st-1; r=n;	//查找A最后出现的位置 
	while(l<r) //因为是最后一次出现,尽量往右,模板2
	{
		int mid=l+r+1>>1;
		if(a[mid]<=a[st]) l=mid; //判断:在目标值的左边,满足,往右去
		else r=mid-1;
	}
	cnt+=l-st+1;}	//最后出现的位置减首次出现的位置就是区间长度,即A的个数 
	System.out.println(cnt);
}

二分先排序不解释

这个题,我们要查找最接近估分的学校的分,那么不妨查找第一个高于估分的学校,答案就是这个学校或者前一个学校与估分之间的分差。

还有边界处理的细节

如果我贼nb,估分超过了最nb的学校,

那么l就为n,a[l]-ta可能为负,则设a[n+1]为无穷大,

并将r设为n+1,如此,l最大为n+1,则最后一个就为解

如果我跟上了爆叔的节奏,估分比最拉的学校分还少 那么l就为1,l-1就为0,故设a[0]为无穷小,则第一个值就为解

代码

package 二分;

import java.util.Arrays;
import java.util.Scanner;

public class 烦恼的高考志愿 {
   public static void main(String[] args) {
	int a[]=new int [100005];
	Scanner sc=new Scanner(System.in);
	
	int n=sc.nextInt();
	int m=sc.nextInt();
	long sum=0;
	for(int i=1;i<=n;i++)
	{
		a[i]=sc.nextInt();
	}
	Arrays.sort(a,1,n+1);
	a[0]=-10000000;a[n+1]=10000000;
	
	for(int i=1;i<=m;i++)
	{
		int ta=sc.nextInt();
		int l=1;int r=n+1;//查找第一个大于估分的学校,那它或它前面的一个学校就是目标学校 
		//int r=n;
		while(l<r)//
		{
		int mid=l+r>>1;
		
		if(a[mid]>=ta)r=mid;
		else  l=mid+1;
		}
		//a[0]=-1e7: 所有分数先可能都比估分大,那么l就为1,l-1就为0,故设a[0]为无穷小,则第一个值就为解 
		//a[n+1]=1e7: 所有分数线可能都比估分小,那么l就为n,a[l]-ta可能为负,则设a[n+1]为无穷大,
					//并将r设为n+1,如此,l最大为n+1,则最后一个就为解 
	
		sum+=Math.min(ta-a[l-1], a[l]-ta);
	
		
	}
   System.out.println(sum);
   }
}

新人博主,坚持更新不易,现在关注绝对不亏~

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值