1.5 排序

电影

算法:排序。

写个排序函数即可。大概就是记录一下每个语言有多少人懂。然后每部电影以能听懂语音的人的数量为第一关键字(从大到小),以能看懂字幕的人的数量为第二关键字(从大到小),电影编号为第三关键字(从小到大)排个序就行了。

货仓选址

算法:排序。

比较简单地,我们可以证明,把货舱放到这些商店的中位数会使距离之和最小。于是排个序求中位数即可。

七夕祭

算法:排序。

首先如果总数量不是行数的倍数,那么行就不能满足,列同理。

然后可以发现,行和列相互独立,于是我们可以分成两个独立的子问题来做。

然后发现这事实上就是一个环形纸牌均分问题。

这里先说一下纸牌均分问题(链式)。比方说给个样例 9 8 17 6,最后每个位置上都应该有 \(10\) 个,求个差得到 -1 -2 7 -4,再弄个前缀和得到 -1 -3 4 0。可以发现,这几个东西的绝对值之和就是我们的操作次数。

所以,我们记平均数为 \(avg\),第 \(i\) 行(列)有 \(a_i\) 个摊位。然后最后每个位置的前缀和数组事实上就是 \(\displaystyle\sum_{j=1}^{i}(a_j)-i\times avg\),注意这个式子就是后面我们转化后的 \(s_i\)

于是,我们考虑如何解决环形纸牌均分问题。可以考虑从一个地方断开,变成上面的问题。显然枚举会使得复杂度不能接受,所以我们考虑一些其他方式。

假设纸牌均分问题的前缀和数组为 \(s_i\)。于是断开后变成了 \(s_{k+1}-s_k,s_{k+2}-s_k,\cdots,s_1+s_n-s_k,\cdots,s_k+s_n-s_k\)。然后我们将原来的 \(a_i\) 每项减去 \(avg\),这里事实上 \(s_i\) 就变成上面那个求和的式子了。然后这里就有 \(s_n=0\)。于是每一项就变成了 \(s_i-s_k\),最后求个绝对值之和。所以目标是找出 \(k\) 使得绝对值之和最小,可以发现这就是货舱选址问题,于是直接取个中位数就做完了。

动态中位数

算法:排序,对顶堆。

首先说一下对顶堆是什么。大概就是开两个堆,一个是大根堆,另一个是小根堆。然后把小于中位数的数放到大根堆里,大于中位数的数放到小根堆里。

然后如果一个堆里的数超过了当前数的数量的一半(上取整),就把这个堆的顶代表的数放进另一个堆里然后把他删掉,直到两个堆中的数的数量相等或者差 \(1\)

超快速排序

算法:归并排序求逆序对。

考虑一个事情,每次交换两个数会带来什么影响。比较显然地,会减少一个逆序对。所以我们如果操作得当,每次都会且仅会减少一个逆序对。所以我们要求的就是原序列的逆序对数量。所以写个归并排序求逆序对即可。

奇数码问题

算法:归并排序求逆序对。

对于这类问题,有一个比较难证明的结论,就是把空格去掉之后,所有数排成一行之后,如果两个状态的逆序对的奇偶性相同,则可以到达,否则不能到达。于是还是写个归并排序求逆序对即可。

posted @ 2024-07-11 21:34  zxh923  阅读(0)  评论(0编辑  收藏  举报