P1631 序列合并,思维,优先队列

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<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
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<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]);
		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;
}

posted @ 2023-10-14 11:44  Landnig_on_Mars  阅读(22)  评论(0编辑  收藏  举报  来源