问题描述
有两个长度为 n n n 的序列 a a a 和 b b b ,在 a a a 和 b b b 中各任取一个数相加可以得到 n 2 n ^ 2 n2 个和,求这 n 2 n ^ 2 n2 个和中最小的 n n n 个。
输入格式
第一行输入一个正整数 n n n 。
第二行 n n n 个整数 a i a_i ai。
第三行 n n n 个整数 b i b_i bi。
输出格式
第一行 n n n 个整数,从小到大输出这 n n n 个最小的和,相邻数字之间用空格隔开。
样例
样例输入1:
5
1 3 2 4 5
6 3 4 1 7
样例输出1:
2 3 4 4 5
数据范围
对于 50 % 50\% 50% 的数据, 1 ≤ n ≤ 1000 1 \le n \le 1000 1≤n≤1000。
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100000 1 \le n \le 100000 1≤n≤100000, 1 ≤ a i , b i ≤ 1 0 9 1 \le a_i, b_i \le 10 ^ 9 1≤ai,bi≤109。
题解
先将 a a a 和 b b b 从小到大排序,显然, a 1 ≤ a 2 ≤ … ≤ a n a_1 \le a_2 \le \ldots \le a_n a1≤a2≤…≤an, b 1 ≤ b 2 ≤ … ≤ b n b_1 \le b_2 \le \ldots \le b_n b1≤b2≤…≤bn。
先将 a 1 + b 1 a_1 + b_1 a1+b1, a 1 + b 2 a_1 + b_2 a1+b2, … \ldots …, a 1 + b n a_1 + b_n a1+bn 放进堆里,并把 a 1 a_1 a1 的编号 1 1 1 记录下来。
最先取出 a 1 + b 1 a_1 + b_1 a1+b1,输出,并继续放入 a 2 + b 1 a_2 + b_1 a2+b1,第二小的在 a 2 + b 1 a_2 + b_1 a2+b1 和 a 1 + b i ( 2 ≤ i ≤ n ) a_1 + b_i(2 \le i \le n) a1+bi(2≤i≤n) 之间。
可以证明其正确性:
a 1 + b i ≤ a 2 + b i ≤ a 3 + b i ≤ … a n + b i a_1 + b_i \le a_2 + b_i \le a_3 + b_i \le \ldots a_n + b_i a1+bi≤a2+bi≤a3+bi≤…an+bi
那么如果取出了 a x + b y a_x + b_y ax+by,则放出大于它的且最接近的 a x + 1 + b y a_{x + 1} + b_y ax+1+by,能保证递增性质。
//定义大根堆 q
priority_queue<pi, vector<pi>, greater<pi>> q;
输入 n, 数组a, 数组b
a, b 从小到大排序
//初始放入
for(int i = 1; i <= n; ++ i){q.push({a[1] + b[i], 1});
}
for(int i = 1; i <= n; ++ i){pi pr = q.top();//输出printf("%d\n", pr.first);q.push({pr.first - a[pr.second] + a[pr.second + 1], pr.second + 1});
}