序列合并
题目链接:ybt高效进阶4-1-2 / luogu P1631
题目大意
有两个长度为 N 的序列,然后两个序列中各任取一个加在一起可以得到长度为 N*N 的序列,问你这个新序列中的最小的前 N 个。
思路
我们考虑因为是相加,我们让加的两个都尽可能小。
那我们就固定一边从小到大,先选小的,再选大的。
但是另一边呢?
我们考虑用这样的一种方法:
每个数一开始都跟另一边的第一个(也就是最小的)对应,然后得出的每个数放进堆里面。
每次你就找到堆中最小的数,然后输出它,把它弹出,然后我们在插入数的时候记录它是那一边的哪个数,然后就插入这个数下一个对应的点。
说的不太清楚,可以看看代码。
代码
#include<queue>
#include<cstdio>
using namespace std;
int n, a[100001], b[100001];
int now[100001];
priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
for (int i = 1; i <= n; i++) {
now[i] = 1;//记录这一边的这个数跟另一边匹配到第几个
q.push(make_pair(a[i] + b[1], i));
}
for (int i = 1; i <= n; i++) {
printf("%d ", q.top().first);
int tmp = q.top().second;
q.pop();
now[tmp]++;//匹配下一个
if (now[tmp] > n) continue;
q.push(make_pair(a[tmp] + b[now[tmp]], tmp));
}
return 0;
}