题目出处:
烦恼的高考志愿 - 洛谷
题目内容:
现有 m(m <= 100000) 所学校,每所学校预计分数线是 ai(ai <= 10^6) 。有n(n <= 100000)位学生,估分分别为 bi(bi <= 10^6)。
根据 n 位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。
输入格式
第一行读入两个整数 m,n。m 表示学校数,n 表示学生数。
第二行共有 m 个数,表示 m 个学校的预计录取分数。第三行有 n 个数,表示 n 个学生的估分成绩。
输出格式
输出一行,为最小的不满度之和。
输入
4 3
513 598 567 689
500 600 550
输出
32
数据规模与约定
数据保证,1 <= n,m <= 100000,估分和录取线 <= 1000000。
思路:二分
设一段为学生选择的分数区段【nl,nr】,nl为选取的左端,nr为右端,最后通过二分法推进让 nl=nr 确定最优满意度情况。
通过判断学生分数落到所有学校的分数线中线的那一端,但是注意中线是通过mid=(nl+nr)/2,除得的商若非整数会向下取整,所以当学生分数在所有学校的分数线中线下端nr=mid;否则nl=mid+1,来防止nl+1=nr时,因为除法得商无法结束循环,以此循环直到nl=nr。
AC代码
#include<bits/stdc++.h>
using namespace std;
int schools[1000005],students[1000005];
int main()
{
int nl,nr,mid,num=0,i,j,m,n;
cin>>m>>n;
for(i=0;i<m;i++)
{
cin>>schools[i];
}
for(i=0;i<n;i++)
{
cin>>students[i];
}
sort(schools,schools+m);
for(i=0;i<n;i++)
{
nl=0; nr=m;
while(nl<nr)
{
mid=(nl+nr)/2;
if(schools[mid]<=students[i])
{
nl=mid+1;//为了防止nl+1=nr时,因为除法得商无法结束循环
}
else nr=mid;
}
if(schools[0]<students[i])
num+=min(abs(schools[nr-1]-students[i]),abs(schools[nr]-students[i]));
else num+=schools[0]-students[i];
}
cout<<num<<endl;
return 0;
}
谢谢。😘