洛谷 P1631 序列合并

 题目传送门

解题思路:

首先,把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个队列的下一个元素放入堆中。

时间复杂度:O(NlogN)。

//以上转载自:https://www.luogu.org/blog/user23845/solution-p1631

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 struct kkk {
 9     int v,xb,js;
10 }p[100001];
11 int n,a[100001],b[100001];
12 priority_queue<kkk> l;
13 
14 bool operator < (kkk a,kkk b){
15     return a.v > b.v;
16 }
17 
18 void shu_ru() {
19     scanf("%d",&n);
20     for(int i = 1;i <= n; i++){
21         scanf("%d",&a[i]);
22         p[i].xb = i;
23         p[i].js = 1;
24     }    
25     for(int i = 1;i <= n; i++)
26         scanf("%d",&b[i]);
27     sort(a+1,a+1+n);
28     sort(b+1,b+n+1);
29 }
30 
31 int main() {
32     shu_ru();
33     for(int i = 1;i <= n; i++) {
34         p[i].v = b[1] + a[i];
35         l.push(p[i]);
36     }
37     for(int i = 1;i <= n; i++) {
38         printf("%d ",l.top().v);
39         kkk u;
40         u.xb = l.top().xb;
41         u.js = l.top().js + 1;
42         l.pop();
43         u.v = a[u.xb] + b[u.js];
44         l.push(u);
45     }
46     return 0;
47 }
原文地址:https://www.cnblogs.com/lipeiyi520/p/11241157.html