poj 2442(堆的stl实现)
2013-11-01 21:51
281 查看
Sequence
Description
Given m sequences, each contains n non-negative integer. Now we may select one number from each sequence to form a sequence with m integers. It's clear that we may get n ^ m this kind of sequences. Then we can calculate the sum
of numbers in each sequence, and get n ^ m values. What we need is the smallest n sums. Could you help us?
Input
The first line is an integer T, which shows the number of test cases, and then T test cases follow. The first line of each case contains two integers m, n (0 < m <= 100, 0 < n <= 2000). The following m lines indicate the m sequence
respectively. No integer in the sequence is greater than 10000.
Output
For each test case, print a line with the smallest n sums in increasing order, which is separated by a space.
Sample Input
Sample Output
Source
POJ Monthly,Guang Lin
首先要深入理解题意:
输入是m行*n列的矩阵。需要从每一行选一个数字,这样会构成m个数字的序列。
对这个序列求和,问最小的n个和是什么。
首先,要深刻理解,我们需要维护多少个数字。因为题目中只要求前n个最小和,我们只需要每步维护n个最小的数字即可。
比如第一行和第二行各挑一个数字求和,可以形成n*n个数字,排个序后,我们只需要保存前n个数字即可,根本不用管其余的数。第三行和上一步形成的这n个数字分别求和,又形成了n*n个数字,排个序后,再只保存前n个数字即可。因此可以逐步迭代计算。
如果按照上面的方法,写一个朴素的暴力算法,则空间复杂度为n*n,时间复杂度为(n*n + n*log(n)) * m 。可是TLE了。。
需要优化。想到用堆。因为事实上我们每步都只需要维护最小的n个数即可。那我们就维护一个大跟堆(注意这里是大跟堆),这个堆含有固定的n个元素(意味着初始化的时候,堆中有n个元素。以后只要插入一个元素,就要删除一个元素来保证堆中元素数目恒定为n)。
这个思路有了以后,再细想一下步骤:每一步先把thisline[0] 和 [lastheap[0], lastheap[n-1]] 分别相加,形成n个数字,建堆thisheap。再用[thisline[1]-thisline[n-1]]与[lastheap[0], lastheap[n-1]]分别求和,依次与thisheap的堆顶(最大值)比较,如果发现比最大值大,则舍弃。发现比最大值小,则删除堆中最大值,将新值push到堆中。
堆的几个重要的stl操作:
stl中的堆都是 大根堆
make_heap(v.begin(), v.end()); 将n个元素的数组建堆
pop_heap(v.begin(), v.end()); 将n个元素的堆的堆顶pop掉。此时数组中的0-n-2是一个有n-1个元素的新堆。被pop掉的原堆顶元素被放到了n-1的位置。因此往往在这一步之后还需要执行
v.pop_back();
push_heap(v.begin(), v.end()); 这一步首先要确保数组中的0-n-2是一个有n-1个元素的堆,而且新元素已经被放置在了v[n-1]位置。调用这个操作会将v[n-1] shiftup到合适的位置。因此在这一步之前要先执行v.push_front(x);
这么做的话,ac需要2600ms+, 如果加一个小小的优化:将thisline先排序,当发现求和大于堆顶元素时,后面的就都不用比较了。这么优化可以400+ms AC。
代码如下:
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 6281 | Accepted: 1962 |
Given m sequences, each contains n non-negative integer. Now we may select one number from each sequence to form a sequence with m integers. It's clear that we may get n ^ m this kind of sequences. Then we can calculate the sum
of numbers in each sequence, and get n ^ m values. What we need is the smallest n sums. Could you help us?
Input
The first line is an integer T, which shows the number of test cases, and then T test cases follow. The first line of each case contains two integers m, n (0 < m <= 100, 0 < n <= 2000). The following m lines indicate the m sequence
respectively. No integer in the sequence is greater than 10000.
Output
For each test case, print a line with the smallest n sums in increasing order, which is separated by a space.
Sample Input
1 2 3 1 2 3 2 2 3
Sample Output
3 3 4
Source
POJ Monthly,Guang Lin
首先要深入理解题意:
输入是m行*n列的矩阵。需要从每一行选一个数字,这样会构成m个数字的序列。
对这个序列求和,问最小的n个和是什么。
首先,要深刻理解,我们需要维护多少个数字。因为题目中只要求前n个最小和,我们只需要每步维护n个最小的数字即可。
比如第一行和第二行各挑一个数字求和,可以形成n*n个数字,排个序后,我们只需要保存前n个数字即可,根本不用管其余的数。第三行和上一步形成的这n个数字分别求和,又形成了n*n个数字,排个序后,再只保存前n个数字即可。因此可以逐步迭代计算。
如果按照上面的方法,写一个朴素的暴力算法,则空间复杂度为n*n,时间复杂度为(n*n + n*log(n)) * m 。可是TLE了。。
需要优化。想到用堆。因为事实上我们每步都只需要维护最小的n个数即可。那我们就维护一个大跟堆(注意这里是大跟堆),这个堆含有固定的n个元素(意味着初始化的时候,堆中有n个元素。以后只要插入一个元素,就要删除一个元素来保证堆中元素数目恒定为n)。
这个思路有了以后,再细想一下步骤:每一步先把thisline[0] 和 [lastheap[0], lastheap[n-1]] 分别相加,形成n个数字,建堆thisheap。再用[thisline[1]-thisline[n-1]]与[lastheap[0], lastheap[n-1]]分别求和,依次与thisheap的堆顶(最大值)比较,如果发现比最大值大,则舍弃。发现比最大值小,则删除堆中最大值,将新值push到堆中。
堆的几个重要的stl操作:
stl中的堆都是 大根堆
make_heap(v.begin(), v.end()); 将n个元素的数组建堆
pop_heap(v.begin(), v.end()); 将n个元素的堆的堆顶pop掉。此时数组中的0-n-2是一个有n-1个元素的新堆。被pop掉的原堆顶元素被放到了n-1的位置。因此往往在这一步之后还需要执行
v.pop_back();
push_heap(v.begin(), v.end()); 这一步首先要确保数组中的0-n-2是一个有n-1个元素的堆,而且新元素已经被放置在了v[n-1]位置。调用这个操作会将v[n-1] shiftup到合适的位置。因此在这一步之前要先执行v.push_front(x);
这么做的话,ac需要2600ms+, 如果加一个小小的优化:将thisline先排序,当发现求和大于堆顶元素时,后面的就都不用比较了。这么优化可以400+ms AC。
代码如下:
相关文章推荐
- POJ 2442 Sequence (STL优先队列)
- POJ 2833 求平均数。 模板:STL实现大根堆和小根堆
- 【POJ】 2442——Sequence【STL—优先队列】
- POJ 2442 Squence (STL heap)
- POJ 2442 Sequence 堆的思想的应用 STL 堆学习
- STL FunctionObject实现 - 2
- POJ - 1338 Ugly Numbers-STL的灵活运用
- 使用boost和stl分别实现超时功能
- STL——模拟实现空间配置器
- 【C++ STL应用与实现】26: 如何使用std::for_each以及基于范围的for循环 (since C++11)
- POJ 3253 Fence Repair STL 优先队列
- 用STL实现字符串字串替换
- poj 3253(哈夫曼树priority_queue实现)
- (使用STL自带的排序函数进行排序7.3.6)POJ 2945 Find the Clones拷贝相同次数的文本出现了多少次()
- 迭代器模拟实现STL中的list
- poj 2442 Sequence (Priority Queue)
- POJ 1146 ID Codes (STL)
- 自定义String类,并且实现在STL容器中添加自定义的类型
- 14.2线性表之STL实现10进制向任意进制的转换
- C++STL 编程技巧1 STL中各种排序算法的实现