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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号