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
#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& a,const pair& b) {
	return a.first > b.first;
}

priority_queue, vector>, greater>>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(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(b[i] + a[to[i]], i));
	}
	return 0;
}

你可能感兴趣的:(数论,数学,思维,算法,数据结构)