题意:有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到个和,求这
个和中最小的N个
题解:先排序得到两个递增的数列a和b,然后用小根堆维护a+b,每次取队首,如果这次取出的是a[i]+b[j],则往队列中
插入a[i]+b[j+1],所以需要另开一个数组p[i]来记录每一个a[i]应该匹配的b。正确性显然:取前k小值等价于取k次当前最小值,如果a[i]+b[j]都没被取到,那a[i]+b[j+1]考都不用考虑,后面的b就更不说了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+4;
int n,a[N],b[N],p[N];
struct Node {
int val,id;
friend bool operator <(Node a,Node b) {
return a.val>b.val;
}
};
priority_queue<Node> q;
inline int read() {
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int main() {
n=read();
for (register int i=1;i<=n;++i) a[i]=read();
for (register int i=1;i<=n;++i) {
b[i]=read(),p[i]=1;
Node cur={a[i]+b[1],i};
q.push(cur);
}
int k=n;
while (k--) {
Node cur=q.top();
q.pop();
int val=cur.val,id=cur.id;
printf("%d ",val);
q.push((Node){a[id]+b[++p[id]],id});
}
puts("");
return 0;
}