P1631 序列合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
有两个长度为 N 的单调不降序列 A,B,在 A,B 中各取一个数相加可以得到 N2 个和,求这 N2 个和中最小的 N 个。
第一行一个正整数 N;
第二行 N 个整数 A1…N。
第三行 N 个整数 B1…N。
一行 N 个整数,从小到大表示这 N 个最小的和。
输入 #1复制
3 2 6 6 1 4 8
输出 #1复制
3 6 7
对于 50% 的数据,3N≤103。
对于 100% 的数据,1≤N≤105,1≤ai,bi≤109。
题目让我们求前n个最小的和
性质:
两个原序列a,b 从小到大排列,我们将a序列的各个值于b序列的第一个值相加,得到n个数,第一小的值一定出现在这n个数中,若当前最小的数是a[i]+b[j]所得,那么用a[i]+b[j+1]将其替换,则下一个最小值还是在这n个数中……。
重复以上过程,最终将获得前n个最小的值
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
- typedef long long LL;
- const int N = 1e5 + 5;
- int n;
- int a[N], b[N], to[N];
-
- bool operator > (const pair<int, int>& a,const pair<int, int>& b) {
- return a.first > b.first;
- }
-
- priority_queue
int, int>, vectorint, int>>, greaterint, 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]);
- q.push(pair<int, int>(a[1] + b[i], i));
- to[i] = 1;
- }
- while (n--) {
- printf("%d ", q.top().first);
- int i = q.top().second;
- q.pop();
- to[i]++;
- q.push(pair<int, int>(b[i] + a[to[i]], i));
- }
- return 0;
- }