嘿嘿,跟对师傅很重要~这里参考下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);
}
}
新人博主,坚持更新不易,现在关注绝对不亏~