洛谷题解——P1678:烦恼的高考志愿

题目相关

题目链接

洛谷,https://www.luogu.com.cn/problem/P1678。

我的OJ,http://47.110.135.197/problem.php?id=4276。

题目描述

现有 m 所学校,每所学校预计分数线是 ai。有 n 位学生,估分分别为 bi​。

根据 n 位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。

输入格式

第一行读入两个整数 m,n。m 表示学校数,n 表示学生数。

第二行有 m 个数,表示 m 个学校的预计录取分数。

第三行有 n 个数,表示 n 个学生的估分成绩。

输出格式

一行,为最小的不满度之和。

输入样例

4 3
513 598 567 689
500 600 550

输出样例

32

数据规模

m ≤ 100000

ai​ ≤ 10^6

n ≤ 100000

bi ​≤ 10^6

题目分析

题意分析

不需要分析,跳过。

样例数据分析

根据输入的样例数据,我们知道一共有 4 所学校,学校的录取分数分别为:513、598、567、689。一共有 3 名考生,高考的分数为:500、600、550。

第一个考生的分数为 500,这个分数在所有高校录取分数 513 以下,因此该学生的不满意度为 513-500=13。

第二个考生的分数为 600,这个分数在所有高校录取分数 598 和 689 之间,因此该学生的不满意度有两个,分别为 600-598=2 和 689-600=89,根据题意,我们取最小值。因此该学生的不满意度为 600-598=2。

第三个考生的分数为 550,这个分数在所有高校录取分数 513 和 567 之间,因此该学生的不满意度有两个,分别为 550-513=37 和 567-550=17,根据题意,我们取最小值。因此该学生的不满意度为 567-550=17。

这三个学生的所有不满度合计为:13+2+17=32。

数据规模分析

ai​ ≤ 10^6,bi ​≤ 10^6。因此对应的分数我们使用 int 可以描述。

m ≤ 100000,n ≤ 100000。这样极限数据应该是所有高校录取分数都是 10^6,而考生分数是 0 分。这样对应的最大值为 10^6*10^6=10^12,超过了 int 的范围。所以答案需要用 long long 来描述。

算法思路

从样例数据分析中,我们可以看出,本题的核心就是根据每个学生的分数,找出比这个分数小的录取分数的最大值和比这个分数大的录取分数的最小值。既然是查找问题,我们肯定可以使用二分查找来实现,二分查找的时间复杂度为 O(logn)。最多的数据为 1e5 个,因此可以满足。

1、读入数据。

2、对高校录取分数进行排序。

3、应该是没有必要进行出重,当然去重也是可以的。

4、对每个学生高考分数,在录取分数中查找左下界和右上界。

5、如果左下界不等于右上界,说明高考分数和某个学校的录取分数相同。也就意味着这个学生的不满度为 0。

6、如果左下界等于右上界,说明学生高考分数在两个高校录取分数之间。需要分类讨论。分布右三种情况:一是小于高校录取分数最小值,这个时候 lo=hi=0,那么不满值应该是(高校录取分数最小值 - 高考分数);二是大于高校录取分数最大值,这个时候 lo=hi=m,那么不满值应该是(高考分数 - 高校录取分数最大值);三是在两个高校录取分数线之间,那么不满足应该右有两个,即(高考分数 - 高校录取分数[lo-1])和(高校录取分数[hi] - 高考分数),我们取最小值即可。

AC 参考代码

根据上面的分析,我们知道核心就是找出考生分数在高校录取分数的左下界(hi)和右上界(lo)。

/*
OJ:luogu
题目:P1678 烦恼的高考志愿
地址:https://www.luogu.com.cn/problem/P1678
*/
#include 

const int MAXM = 1e5+2;
int a[MAXM];//学校分数
const int MAXN = 1e5+2;
int b[MAXM];//学生分数

int main() {
    int n, m;
    scanf("%d%d", &m, &n);

    int i;
    //读入学校分数
    for (i=0; i=m) {
                ans += (b[i]-a[hi-1]);
            } else {
                ans += std::min(b[i]-a[lo-1], a[hi]-b[i]);
            }
        }        
    }
    printf("%llu\n", ans);

    return 0;
}

代码细节

就是对 hi 和 lo 的值进行分类讨论。

你可能感兴趣的:(OJ题解,#,洛谷题解,洛谷题解,P1678,烦恼的高考志愿,二分查找)