题目链接
http://poj.org/problem?id=2442
分析
两两合并,对于两个序列 A A A 和 B B B,先将 A [ 1 ] + B [ i ] A[1] + B[i] A[1]+B[i] 加入堆中, 1 ≤ i ≤ n 1 \leq i \leq n 1≤i≤n。
每次取出的堆顶,即是当前最小和,设取出了 A [ i ] + B [ j ] A[i] + B[j] A[i]+B[j],再将 A [ i + 1 ] + B [ j ] A[i + 1] + B[j] A[i+1]+B[j] 加入堆中。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 2e3 + 5;
struct Node {
int a, sum;
Node(int a = 0, int s = -1) : a(a), sum(s) {}
bool operator < (const Node& rhs) const {
return sum < rhs.sum;
}
};
struct Heap {
int tot;
Node h[maxn];
void up(int p) {
while (p > 1) {
if (h[p] < h[p / 2]) swap(h[p], h[p / 2]), p /= 2;
else break;
}
}
void down(int p) {
while (2 * p <= tot) {
int q = 2 * p;
if (q + 1 <= tot && h[q + 1] < h[q]) ++q;
if (h[q] < h[p]) swap(h[q], h[p]), p = q;
else break;
}
}
void insert(Node x) {
h[++tot] = x;
up(tot);
}
Node get_top() {
return h[1];
}
void remove(int p = 1) {
h[p] = h[tot--];
up(p), down(p);
}
} h;
int a[maxn], b[maxn], c[maxn];
int main() {
int t = read();
while (t--) {
int m = read(), n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
sort(a + 1, a + n + 1);
for (int i = 2; i <= m; ++i) {
h.tot = 0;
for (int j = 1; j <= n; ++j) b[j] = read();
sort(b + 1, b + n + 1);
for (int j = 1; j <= n; ++j) h.insert(Node(1, a[1] + b[j]));
for (int j = 1; j <= n; ++j) {
int p = h.get_top().a;
c[j] = h.get_top().sum;
h.remove();
h.insert(Node(p + 1, a[p + 1] + c[j] - a[p]));
}
for (int j = 1; j <= n; ++j) a[j] = c[j];
}
for (int i = 1; i <= n; ++i) printf("%d ", a[i]);
puts("");
}
return 0;
}