P1678 烦恼的高考志愿 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)P1678 烦恼的高考志愿 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题刚开始没看明白,求所有学生不满意度和的最小值,我以为是把每个学生与各个录取线的差值相加,求一个最小值。
后来看样例看明白了:
我们需要根据学生预估分与找与它差值最小的录取线:
也就是 把每个学生的预估分每个录取线相减,求出最小差值,这样不满意度最小。
最后把所有差值和相加,得到的就是不满意度和的最小值。
解题思路
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[100005], b[100005];
int n, m;
int ans;
signed main()
{
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<m;i++)cin>>b[i];
sort(a,a+n);//排序
for(int j=0;j<m;j++) //估分
{ int tol=INT_MAX;
for(int i=0;i<n;i++) //学校录取线每次都要全部遍历一次 ,找出与估分差值最小的
{
tol=min(tol,abs(a[i]-b[j]));
}
ans+=tol;
}
cout<<ans;
return 0;
}
n,m最大1e5,两层循环就超时了,所以可以用二分去找,二分是:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[100005], b[100005];
int n, m;
int ans;
signed main()
{
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<m;i++)cin>>b[i];
sort(a,a+n);//排序
//开始二分查找
for(int i=0;i<m;i++)
{
int l=0,r=n-1,tol=0x7fffffff;
while(l<=r)
{
int mid=l+r>>1;
if(a[mid]<b[i])
{
tol=min(tol,abs(b[i]-a[mid]));
l=mid+1;
}
else
{
r=mid-1;
tol=min(tol,abs(b[i]-a[mid]));
}
}
ans+=tol;
}
cout<<ans<<endl;
return 0;
}