这是一道练习二分的不错的题目。因为每组数据的答案的范围都可以被算出来,所以就可以对答案进行二分然后判断该答案是否合法即可,这样时间复杂度也会降到 $\log$ 级别,所以不会超时。
先来看看如何求答案的范围。为了方便程序的计算,以下保证 $n \le m$ (若出现 $n >m$ 的情况,则输入完毕后将 $n,m$ 以及 $L_i,R_i$ 进行交换)。对于所有左脚鞋 $L_i$ 都有一个右脚鞋 $R_i$ 满足 $L_i = R_i$ 的情况,则最小的答案为 $0$;将左右脚鞋子分别进行排序,由题对丑陋度的定义可知,最大的答案为 $\min (|L[1] - R[m]|,|R[1] - L[n]|)$。
得知范围后,接下来就是对答案的二分了。二分目的是要找到一个最小的合法答案,因此要写成 r = mid 与 l = mid + 1。
1 | while (l < r) |
那么如何判断解是否合法呢?设当前的待判断的答案为 $num$,用数量较少的鞋子去匹配数量较多的鞋子(由于前文规定了 $n < m$,也就是用左脚鞋去匹配右脚鞋),利用贪心的思想,对于每一只已经从小到大排好的左脚鞋,要找到一只右脚鞋满足 $|L_i - R_j| \le num$ 后再去匹配下一只左脚鞋。若在左脚鞋满足在范围内全部成功与右脚鞋匹配的情况,则答案合法,否则不合法。
1 | bool check (int num)//to check whether the answer is correct or not |
最后退出循环 while (l < r) 后得到的 $l$ 就是答案啦!