P1631

序列合并

题目描述

有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到\(N^2\)个和,求这\(N^2\)个和中最小的N个。

输入格式

第一行一个正整数N;

第二行N个整数\(A_i\), 满足\(A_i\le A_{i+1}\)\(A_i\le 10^9\);

第三行N个整数\(B_i\), 满足\(B_i\le B_{i+1}\)\(B_i\le 10^9\).

【数据规模】

对于50%的数据中,满足1<=N<=1000;

对于100%的数据中,满足1<=N<=100000。

输出格式

输出仅一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。

样例 #1

样例输入 #1

3
2 6 6
1 4 8

样例输出 #1

3 6 7
首先,把A和B两个序列分别从小到大排序,变成两个有序队列。这样,从A和B中各任取一个数相加得到N2个和,可以把这些和看成形成了n个有序表/队列:

A[1]+B[1] <= A[1]+B[2] <= … <= A[1]+B[N]

A[2]+B[1] <= A[2]+B[2] <= … <= A[2]+B[N]

……

A[N]+B[1] <= A[N]+B[2] <= … <= A[N]+B[N]

接下来,就相当于要将这N个有序队列进行合并排序:

首先,将这N个队列中的第一个元素放入一个堆中;

然后;每次取出堆中的最小值。若这个最小值来自于第k个队列,那么,就将第k个队列的下一个元素放入堆中
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[1000005],b[1000005];
struct did{
	int v,id,num;
	friend bool operator < (did a,did b){return b.v<a.v;}
};
priority_queue<did>q;
signed main() 
{
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];		
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++){did z;z.v=a[i]+b[1];z.id=i;z.num=1;q.push(z);}
	int cnt=0;
	while(1)
	{
		if(cnt==n)break;
		cnt++;
		did z=q.top();q.pop();
		cout<<z.v<<" ";
		int id=z.id,num=z.num;
		did t;t.id=id,t.num=z.num+1,t.v=a[id]+b[num+1];
		q.push(t);
	}
	return 0;
}
posted @ 2023-01-21 09:37  PKU_IMCOMING  阅读(37)  评论(0)    收藏  举报