P1678 烦恼的高考志愿 二分,混搭排序

题目背景

计算机竞赛小组的神牛V神终于结束了高考,然而作为班长的他还不能闲下来,班主任老t给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是v神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。

题目描述

现有 m(m≤100000)m(m\le100000)m(m100000) 所学校,每所学校预计分数线是 ai(ai≤106)a_i(a_i\le10^6)ai(ai106)。有 n(n≤100000)n(n\le100000)n(n100000) 位学生,估分分别为 bi(bi≤106)b_i(b_i\le10^6)bi(bi106)。

根据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。

 

首先转换题意

给定n个数,m次询问,每次询问会给出一个数a,要求从n个数中找到一个最接近a的数字b,求出a和b的差值的绝对值并累加,最后求m次差值之和的最小值

问题就很显然了,如何快速的在一组数中找到与a最接近的数字呢

由于一组数已经给出,且有多次询问,很容易想到先对一组数进行排序,然后二分查找

由此引出第一个思路:排序+lower_bound

由于lower_bound返回的是第一个大于等于a的数字,我们并不知道这个数字前一个数字与a的差值会不会更小,因此要在这里两个数中取差值最小,然后对于a比所有数都大和a比所有数都小的情况特判一下,大功告成

 

然后是第二个很巧妙的思路:混合排序

直接将m次询问的数标记后和给定的n个数存在一个数组里,然后一起排序,接着扫一遍,找到被标记的询问数,就看它前后的数字和它的差值取最小,最后对于第一个和最后一个数特判一下即可

然而上面的解法是有bug的,如果询问了多次相同的数,就会在排序后出现aaa的情况,中间的a与前后数的差值都是0,这个结果显然是不对的

有两种解决的办法,第一种是从这个数同时向前向后找,用找到的第一个非标记数来计算差值;第二个是在输入时便用桶排将相同的询问数直接合并,计算时把差值乘以对应询问数出现的次数即可

 

贴上第一种思路的代码

#include<bits/stdc++.h>
using namespace std;
long long  n,m,a[1000005],b[1000005],ans;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
       cin>>a[i];
    for(int i=1;i<=m;i++)
       cin>>b[i];
    sort(a+1,a+n+1);
    
//    for(int i=1;i<=n;i++)
//       cout<<a[i]<<" ";
//       cout<<endl;
       
       
    for(int i=1;i<=m;i++)//其实这一步完全可以边读入边做,然而最后并没有TLE,就懒得改了
       {
           int k=lower_bound(a+1,a+n+1,b[i])-a;
           if(k==n+1)
           {
           ans+=b[i]-a[n];    
           continue;    
           }
           if(k==1)
           {
           ans+=a[1]-b[i];    
           continue;    
           }
           ans+=min(abs(a[lower_bound(a+1,a+n+1,b[i])-a-1]-b[i]),abs(a[lower_bound(a+1,a+n+1,b[i])-a]-b[i]));
       }
    cout<<ans;   
    return 0;
}

 

posted @ 2021-08-29 21:43  pcpcppc  阅读(102)  评论(0编辑  收藏  举报