http://www.yyycode.cn/index.php/2020/07/03/p1678-%e7%83%a6%e6%81%bc%e7%9a%84%e9%ab%98%e8%80%83%e5%bf%97%e6%84%bf/
https://www.luogu.com.cn/problem/P1678
计算机竞赛小组的神牛V神终于结束了万恶的高考,然而作为班长的他还不能闲下来,班主任老t给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是v神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。
现有 m(m\le100000)m(m≤100000) 所学校,每所学校预计分数线是 a_i(a_i\le10^6)ai(ai≤106)。有 n(n\le100000)n(n≤100000) 位学生,估分分别为 b_i(b_i\le10^6)bi(bi≤106)。
根据n位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。
第一行读入两个整数m,n。m表示学校数,n表示学生数。第二行共有m个数,表示m个学校的预计录取分数。第三行有n个数,表示n个学生的估分成绩。
一行,为最小的不满度之和。
输入 #1复制
4 3 513 598 567 689 500 600 550输出 #1复制
32数据范围:
对于30%的数据,m,n<=1000,估分和录取线<=10000;
对于100%的数据,n,m<=100,000,录取线<=1000000。
思路:枚举每个学生找绝对值最近的学校分数线,提前sort二分查,找一个<=x的,一个>=x的,再比较。注意一下二分找不到的时候的边界问题
#include<iostream> #include<vector> #include<queue> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+10; typedef long long LL; LL sch[maxn]; LL stu[maxn]; LL bsearch1(LL l,LL r,LL q) { while(l<r) { LL mid=(l+r)>>1; if(sch[mid]>=q) r=mid; else l=mid+1; } return l; } LL bsearch2(LL l,LL r,LL q) { while(l<r) { LL mid=(l+r+1)>>1; if(sch[mid]<=q) l=mid; else r=mid-1; } return l; } int main(void) { cin.tie(0);std::ios::sync_with_stdio(false); LL m,n;cin>>m>>n; for(LL i=1;i<=m;i++) cin>>sch[i]; for(LL i=1;i<=n;i++) cin>>stu[i]; sort(sch+1,sch+1+m);sort(stu+1,stu+1+n); LL sum=0; for(LL i=1;i<=n;i++) { LL t1=bsearch1(1,m+1,stu[i]); LL t2=bsearch2(0,m,stu[i]); if(t1==m+1) t1=m; if(t2==0) t2=1; LL t=min(fabs(stu[i]-sch[t1]),fabs(stu[i]-sch[t2])); sum+=t; } cout<<sum<<endl; return 0; }