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;
}