XYD 8/1 归并排序与逆序对的性质以及应用
归并排序与逆序对
在归并排序的过程中,由于会涉及到两个序列的首位比较,如果我们作升序排序并且 \(a_{left} > a_{right}\),又因为左右序列都已经有序,所以 \(left\) 左边的数也可以构成逆序对,每次的贡献为 \(mid - left + 1 (mid = \frac{left+right}{2})\)
例题
1.求逆序对
逆序对模板,直接用归并排序套即可。
2.最小点对
大意:在一个平面上有 \(n\) 个点,求在所有点对中两点距离的最小值。
我们采用分治的思想,将所有点按照 \(x\) 轴排序,然后再按照 \(y\) 轴排序。
那么此时的线段有三种情况,\(mid\) 左边,\(mid\) 右边,和跨越 \(mid\)。在左右两边直接取最小值就行了,然后在左右取到 \(mid\) 的 \(x\) 轴坐标距离小于当前答案的某几个点。然后在这些点对中取最小值与答案进行比较。
其中要点对的 \(y\) 轴坐标之差大于等于当前最小答案的情况,因为 \(y\) 轴的距离都大于答案了,那么就肯定不是最优解。
3.疯狂的作业
考虑贪心,第一次做精力值最大的作业,然后去做最小的作业,保证差最大,然后去做次大的作业,就这样一直贪心,直到作业都做完。
4.眼红的Medusa
我们可以使用 map 这个数据结构,存放每个人获奖的顺序和编号。在第二次读入获奖名单时,如果发现这个人在 map 中有过记录,那么把这个人放入答案数组中,最后获奖顺序排序即可。
5.小埋的怪兽游戏
使用树状数组来记录逆序对,将原数组排序后离散化。设 \(dis_i\) 表示第一个大于 \(a_i\) 的数的值,注意,这里 \(a_i\) 已经排好序并且离散化过了,然后我们就可以从大到小,使用树状数组来计算逆序对。
6.编程组队
依旧使用贪心,将原数组从小到大排序,\(1,2\) 一组,\(3,4\) 一组,就这样分下去,那么答案就是 \(a_2 - a_1 + a_4 - a_3 + a_6 - a_5 + ... + a_n - a_{n-1}\)。
7.交换拼图
我们发现 \(h\) 和 \(w\) 都非常的小,所以我们可以枚举每一列和每一行的交换情况,这一点全排列可以做到,接着核对是否与 \(B\) 矩阵相同。计算交换次数也非常简单,我们对每一行和每一列进行编号。那么当交换行或列时,就会产生一个逆序对,所以我们要计算行编号和列编号的逆序对,答案就是逆序对总和的最小值。
8.独木桥
毒瘤
9.母舰
可以使用 upper_bound 来计算攻击防御系统所要使用的攻击力最小的攻击系统。这样可以使得真实伤害更高。当然,还要计算防御系统的剩余个数,如果大于 \(0\),而且我们的攻击系统已经全部使用了,那么只好输出 \(0\),因为我们没法再攻击了。(这道题数据太水了,建议加强o( ̄▽ ̄)ブ)
10.坐标排序
直接开一个 pair 然后按 \(x\) 轴和 \(y\) 轴排序就好了。
11.Fib 斥数
现预处理斐波那契数列的前 \(30\) 项,此时 \(fib_{30}\) 已经过万,不用担心约数太多。然后采用 \(O(\sqrt {n})\) 的分解约数算法,先处理一个数的约数的前一半,然后就可以处理后一半的约数了。记得对一个数的所有约数进行排序。然后直接进行模拟判断约数是否互质就可以了。
总结
-
归并排序
-
归并排序求逆序对
-
树状数组求逆序对
-
贪心
-
二分

浙公网安备 33010602011771号