P1631 序列合并
- 236通过
- 657提交
- 题目提供者xmyzwls
- 标签堆
- 难度普及+/提高
提交该题 讨论 题解 记录
最新讨论
- 为什么不行?
题目描述
有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到N^2个和,求这N^2个和中最小的N个。
输入输出格式
输入格式:
第一行一个正整数N;
第二行N个整数Ai,满足Ai<=Ai+1且Ai<=10^9;
第三行N个整数Bi, 满足Bi<=Bi+1且Bi<=10^9.
【数据规模】
对于50%的数据中,满足1<=N<=1000;
对于100%的数据中,满足1<=N<=100000。
输出格式:
输出仅一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。
输入输出样例
输入样例#1:
3
2 6 6
1 4 8
输出样例#1:
3 6 7
分析:这道题和果子合并非常像,每次都是取2个最小的数,但是本题中每个数可以取多次,但是数对不能重复,但是算法还是一样的,利用优先队列.
由于本题中的数据已经排好序了,所以如果选取了坐标为i,j的两个数,那么下一次可能选i+1,j或i,j+1,这样的话由于每个数可以取多次容易重复,所以使用SET判重,这样的话由于要使用两个结构体,比较容易写错.
还有一种比较简单的方式,首先不管怎么样,A序列中的第一个数绝对要选,那么这个数可能和B序列中的任何一个数组成的数对被选,全部加入优先队列中,这样处理了i,j+1的情况,但是还有i+1,j的情况,每次输出一个和之后,将B序列中的第i个数对应的A序列中的第j个数的j++.
怎么解决数对的重复呢?因为输出的是单调的,我们只需要把上次输出的结果和这次的结果比较看是不是相同就好了.
#include <cstdio>#include <cstring>
#include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <set> using namespace std; int n,cnt; long long a[100010],b[100010]; struct node { int x,y; bool operator < (const node &aa) const { return a[x] + b[y] > a[aa.x] + b[aa.y]; } }; priority_queue <node> q; int main() { scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%lld",&a[i]); for (int i = 1; i <= n; i++) scanf("%lld",&b[i]); sort(a + 1, a + n + 1); sort(b + 1, b + n + 1); for (int i = 1; i <= n; i++) { node temp; temp.x = 1; temp.y = i; q.push(temp); } long long t = 0; while (cnt != n) { node u = q.top(); q.pop(); if (a[u.x] + b[u.y] != t) { cnt++; printf("%lld ",a[u.x] + b[u.y]);
} u.x++; q.push(u); } return 0; }