题意简述
一个大小为的方阵,每行都选一个数,得到一个和。一共能得到个和。求出最小的前个。重复的算多次。。
思路框架
每两行都来一个多路归并即珂。
具体思路
今天去看了刘汝佳的小蓝书。感谢刘汝佳,让我知道优先队列原来还能这么用。
首先,每行里面顺序不重要,先排序再说。
前置知识:n路归并问题
我们应该都知道“二路归并”问题:两个有序的序列,要合并成一个有序的序列。解法很简单,维护两个指针,哪个小就把哪个加入答案,然后让指针++。利用它,我们珂以写出大名鼎鼎的「归并排序」算法。
路归并问题就是:个序列,每个序列都是有序的。要合并成一个长度为的有序的序列。
但是我们发现,我们要维护个指针,一次维护指针是的,我们一共有的元素,就变成了。怎么样更快呢?我们珂以用优先队列来找到值最小的那个指针。这样维护一次指针是的,总共就是的了。而且原问题中我们只需要求前面的个,所以这会更快,变成每次的时间。
如何转化
我们的原问题是有行个和的,如何转化?
首先我们珂以每两行之间逐个合并。然后对于两行和的问题,我们只需要生成这样个序列即珂:
第一个:。
第二个:。
…
第个:。
然后跑一个路归并即珂。这样做次,每次都只求前面个小的,我们就珂以求出个和中最小的个了。
实现细节:关于如何维护指针
如果您足够强,您完全不用看这个。
我们维护两个值,。表示目前的,表示在中的下标。我们完全不用知道中的下标,因为是不会改变的。我们有,下一个指针其实就是。
在优先队列中,我们显然是要以为关键字判断优先级的。
—— 刘汝佳的思路
代码
1 |
|