题目大意
给出两个序列 a , b a, b a,b,将所有的 a i + b i a_i + b_i ai+bi 求出后然后排序,只需要输出其中的前 n n n 个。
解题思路
这题的思路很巧,是利用归并的思想。
将 a , b a,b a,b 均排好序之后,我们在取的时候发现是有技巧的取的,如果 a i + b i a_i + b_i ai+bi 能取就肯定不会取 a i + 1 + b i a_{i+1}+ b_i ai+1+bi 或者 a i + b i + 1 a_i + b_{i +1} ai+bi+1。
我么可以将其中的每 n n n 个数看做 n n n 个有序的队列:
a 1 + b 1 ≤ a 1 + b 2 ≤ . . . ≤ a 1 + b n a_1 + b_1 \leq a_1 + b2 \leq ... \leq a_1 + b_n a1+b1≤a1+b2≤...≤a1+bn
a 2 + b 1 ≤ a 2 + b 2 ≤ . . . ≤ a 2 + b n a_2 + b_1 \leq a_2 + b2 \leq ... \leq a_2 + b_n a2+b1≤a2+b2≤...≤a2+bn
a 3 + b 1 ≤ a 3 + b 2 ≤ . . . ≤ a 3 + b n a_3 + b_1 \leq a_3 + b2 \leq ... \leq a_3 + b_n a3+b1≤a3+b2≤...≤a3+bn
…
a n + b 1 ≤ a n + b 2 ≤ . . . ≤ a n + b n a_n + b_1 \leq a_n + b2 \leq ... \leq a_n + b_n an+b1≤an+b2≤...≤an+bn
根据归并的思想,我们只需要给每个序列一个指针,然后取 n n n 个队列中的最小值,这个最小值可以用优先队列维护,这样就能在时间复杂度之内取出前 n n n 个数了。
#include <bits/stdc++.h>
using namespace std;
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const double eps = 1e-4;
const int Mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 10;
int n;
int a[maxn], b[maxn];
struct node {
int i, j, val;
bool operator<(const node &p) const {
return val > p.val;
}
};
priority_queue<node> q;
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
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]);
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++) q.push({i, 1, a[i] + b[1]});
int m = n;
bool flag = 0;
while (m--) {
node cur = q.top();
q.pop();
printf("%d ", cur.val);
q.push({cur.i, cur.j + 1, a[cur.i] + b[cur.j + 1]});
}
return 0;
}