给定k个有序表,取其中前n小的数字。组成一个新表,求该表?
算法:
由于 a1[1] < a1[2] < a1[3] ... <a1[n]
a2[1] < a2[2] < a2[3] ... < a2[n]
.........
ak[1] < ak[2]<ak[3]...... < ak[n]
首先每个有序表的第一个元素入堆,然后最小元素出堆。该元素入新表L,相应线性表的下一个元素入堆。
例如:如果出堆得是a2[2],那么a2[3]入堆。所以给每一个表增设一个标记。循环n次得到新表.
Pro. 2
给定两个长为n的有序表A,B,根据两表中任意两元素和得到一个大小为N^2的表,得到的新表的前n小的元素。(HDU上的一个。但是那个题目直接Hash做)
根据题意:
A[1] + B[1] < A[1] + B[2] .. < A[1] + B[n]
A[2] + B[1] < A[1] + B[2] .. < A[1] + B[n]
.......
A[n] + B[1] < A[1] + B[2] .. < A[1] + B[n]
这样就得到了n个有序表。 转化为pro 1 得到答案
Pro. 3
说到正题了。 给定m 个长为n 的有序表。 每个表取一个元素。得到m个元素。求和。 要求,求前n小的和。
每次考虑两个表, 根据 a[1][1 ...n] 与a[2][1...n] ,转化为pro.2 。求出一个大小为n的表 L
再考虑表L与a[3][1...n] 得到新的表L'
接着考虑a[4][1....n]
...... 最后得到的本题的答案
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 6259 | Accepted: 1953 |
Description
Input
Output
Sample Input
1
2 3
1 2 3
2 2 3
Sample Output
3 3 4
Source
POJ Monthly,Guang Lin
#include <iostream>
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; int t,n,m,A[2222],Q[2222]; struct node { int arr,id; bool operator < (const node b) const { return arr>b.arr; } }; int matrix[2222][2222]; void fuuuuuc() { int cur=0; int nowfrom[2222]; memset(nowfrom,0,sizeof(nowfrom)); priority_queue<node> q; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { matrix[i][j]=Q[i]+A[j]; if(j==0) { node x; x.arr=matrix[i][0]; x.id=i; q.push(x); } } } /* for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<matrix[i][j]<<" "; } cout<<endl; } */ for(cur=0;cur<n;cur++) { node u=q.top(); q.pop(); // cout<<" -->: "<<u.id<<" "<<u.arr<<endl; int ID=u.id; Q[cur]=u.arr; nowfrom[ID]++; u.arr=matrix[ID][nowfrom[ID]]; q.push(u); } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); for(int i=0;i<n;i++) { scanf("%d",&Q[i]); } sort(Q,Q+n); for(int i=1;i<m;i++) { for(int j=0;j<n;j++) { scanf("%d",A+j); } sort(A,A+n); fuuuuuc(); } for(int i=0;i<n;i++) { if(i) putchar(' '); printf("%d",Q[i]); } putchar(10); } return 0; } |