POJ-2442 Sequence(手写堆优化)

Sequence

Time Limit: 6000MS   Memory Limit: 65536K
Total Submissions: 9131   Accepted: 3037

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

1
2 3
1 2 3
2 2 3

Sample Output

3 3 4

Source

POJ Monthly,Guang Lin

首先这题是可以用系统给的priority_queue的,不过毕竟现在我在学手写堆,于是就给自己找麻烦咯~

思路: 因为,要每行都取一个,构成一个和sum。需要找出n个sum。  我们需要一行一行的找,不妨先设前两行的最小的n个sum是由第一行n个数和第二行的第一个数构成的。 存入c[]数组里,然后一次遍历第二行其他的数,看是否有小于c[]数组里最大的数,然后替换,这是前两行的最小的n个sum已经找到,存到了c[]数组, 然后找前三行,同样设让第三行的第一个数与数组c[]所有的数加和, 然后遍历第三行其他的数,看是否有小于c[]数组里最大的数。替换。以此类推。找到第m-1行  结束寻找,这时数组c[]里就是题目要求的数组。

思路来源:http://www.tuicool.com/articles/VjuYFn

程序压了一点行,可能可读性会差一点

 1 #include "bits/stdc++.h"
 2 #define mem(a,b) memset(a,b,sizeof(a))
 3 #define F(z,x,y) for (z=x;z<=y;z++)
 4 using namespace std;
 5 typedef long long LL;
 6 const int MAX=2005;
 7 int cas;
 8 int n,m;
 9 int s[MAX],sum[MAX];
10 struct Que{
11     int h[MAX*100];
12     int n;
13     Que (){
14         mem(h,0);
15         n=0;
16     }
17     void heapify(int x){
18         int child=x*2,key=h[x];
19         while (child<=n){
20             if (child<n && h[child]<h[child+1]) child++;
21             if (key<h[child]){h[x]=h[child];x=child,child=x*2;}
22             else break;
23         }
24         h[x]=key;
25     }
26     void insert(int key){
27         int x=++n;
28         while (x>1){
29             if (key>h[x/2]) h[x]=h[x/2],x/=2;
30             else break;
31         }
32         h[x]=key;
33     }
34     void del(){
35         if (n==1) n=0;
36         else h[1]=h[n--],heapify(1);
37     }
38 };
39 int main(){
40     freopen ("sequence.in","r",stdin);
41     freopen ("sequence.out","w",stdout);
42     int i,j,k;
43     scanf("%d",&cas);
44     while (cas--){
45         scanf("%d%d",&n,&m);
46         mem(s,0),mem(sum,0);
47         Que q;
48         F(i,1,m){
49             scanf("%d",s+i);
50         }
51         F(i,2,n){
52             F(j,1,m)
53              scanf("%d",sum+j);
54             F(j,1,m)
55              q.insert(sum[1]+s[j]);
56             F(j,2,m)
57              F(k,1,m){
58                  int mx=sum[j]+s[k];
59                  if (mx<q.h[1]){
60                      q.del();
61                      q.insert(mx);
62                  }
63              }
64             F(j,1,m)
65              s[j]=q.h[j];
66             mem(q.h,0);
67             q.n=0;
68         }
69         sort(s+1,s+m+1);
70         F(i,1,m){
71             printf("%d ",s[i]);
72         }
73         printf("\n");
74     }
75     return 0;
76 }
时间: 2024-10-13 16:38:40

POJ-2442 Sequence(手写堆优化)的相关文章

POJ 2442 Sequence(堆的使用练习)

题目地址:POJ 2442 真心没想到这题的思路..原来是从第一行逐步向下加,每次都只保存前n小的数.顺便练习了下堆..不过感觉堆的这种用法用的不太多啊.. 又是手残..把j写成了i,于是就改啊改..改的跟题解上的几乎一样了= = !.. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #inc

[ACM] POJ 2442 Sequence (堆的性质)

Sequence Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7011   Accepted: 2262 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

POJ 2442 Sequence【堆】

题目链接:http://poj.org/problem?id=2442 题目大意:给出一个m*n的矩阵,从每一行中取出一个数相加,能得到n^m个不同的结果,要求输出其中前n项. 建立一个以n元数组为底层数组的堆,在这里,利用stl中的make_heap,pop_heap,push_heap等函数解决. 1.将第一组数据输入arr1数组,升序排序. 2.将接下来的数据输入到arr2数组中,并且heap[i]=arr1[0]+arr2[0...n-1],make_heap(heap,heap+n).

Poj 1151 Invitation Cards dijkstra 堆优化

很裸的最短路,不过节点数和边数都是1e6,直接dij肯定是不行了,稀疏图用heap优化一下就好 o(╯□╰)o注意STL里面的优先队列是优先级大的(值大的)在前面的,一开始没注意WA了好几发,哎,太粗心了 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #inc

Luogu [P1334] 瑞瑞的木板(手写堆)

其实这个题完全不需要用手写堆,只需要一遍遍sort就行了…… 但是! 为了练习手写堆,还是用手写堆做了. 在做本题之前,如果你没有什么思路的话,建议先做Luogu的合并果子. 好,假设你已经做过了合并果子了.那么正式开始本题: 相信许多人都已经知道了这道题就是合并果子,但是还不知道它是怎样转化成合并果子的,其实很简单:比如说9 7 6 5 3,有些同学可能会想:每次我砍最大的,然后剩下的不就少了.其实不然,因为不一定一次只能砍一个,可以砍两个或两个以上.不多说,我把上面例子的最优策略讲出来大概就

poj 2442 Sequence 优先队列的运用

题意: 给m行,每行n个数,从每行取一个数计算和,求前n小的和. 分析: 优先队列的运用,主要是make_heap,pop_heap,push_heap三个STL函数的用法. 代码: //poj 2442 //sep9 #include <iostream> #include <algorithm> using namespace std; const int maxN=2048; int a[maxN],b[maxN],sum[maxN]; int main() { int ca

单源最短路(手写堆+位运算优化+卡常+O2 = Luogu排名最后一页...)

如题 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #define rep(i,a,n) for(register int i = a;i <= n;++i) 6 using namespace std; 7 8 void read(int& a){ 9 a = 0;char c = getchar(); 10 while(c &l

手写堆

自己写的堆,在luogu评测机上完爆stl(400+ms) 有兴趣的可以粘走. #ifndef __HEAP__ #define __HEAP__ #ifdef __cplusplus #include<iostream> #include<cstdio> #include<cctype> using namespace std; struct SHEAP{ int *heap; int num; SHEAP(int size){num=0;heap=new int[s

BZOJ 1975 魔法猪学院(A*+手写堆)

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1941  Solved: 595 [Submit][Status][Discuss] Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig