题目背景
计算机竞赛小组的神牛V神终于结束了高考,然而作为班长的他还不能闲下来,班主任老t给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是v神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。
题目描述
现有 m(m≤100000) 所学校,每所学校预计分数线是 ai(ai≤106)。有 n(n≤100000) 位学生,估分分别为 bi(bi≤106)。
根据n位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。
输入格式
第一行读入两个整数m,n。m表示学校数,n表示学生数。第二行共有m个数,表示m个学校的预计录取分数。第三行有n个数,表示n个学生的估分成绩。
输出格式
一行,为最小的不满度之和。
输入输出样例
输入 #1
4 3
513 598 567 689
500 600 550
输出 #1
32
解题思路:1.循环结束的条件是left<(right-1),这样能保证最后的left和right指向的不是一个元素,因为这样循环结束的条件是left==right-1,如果是正常的二分查找,这里是left <=right,这样跳出循环的条件就是left>right,一旦到了这里,就说明没有找到。
2.如果发现查找的值比中间的值大,left=mid,因为这里是要确定一个区间,如果mid 刚好是区间的左边,那么正确的区间就是mid到right。
知识点:关于Arrays.sort(school,1,m+1);
代码
import java.util.*;
public class 烦恼的高考志愿 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int m=sc.nextInt();//学校数
int n=sc.nextInt();//学生数
int[] school=new int[m+1];
int[] stu=new int[n+1];
for(int i=1;i<=m;i++)
school[i]=sc.nextInt();
for(int j=1;j<=n;j++)
stu[j]=sc.nextInt();
//代表对数组中下标1到m+1中的数进行排序
Arrays.sort(school,1,m+1);
int sum=0,x=0;
for(int i=1;i<=n;i++) {
int left=1,right=m;
//这样能保证学生成绩在两个学校之间,如果是left<right,得到的就会是left==right
while(left<(right-1)) {
int mid=(left+right)/2;
if(stu[i]>=school[mid]) {
left=mid;
}
else right=mid;
}
//找到学生估值所在哪两个学校的录取分数线之间
x=Math.min(Math.abs(stu[i]-school[left]),Math.abs(school[right]-stu[i]));
sum+=x;
}
System.out.print(sum);
}
}