[luoguP1631] 序列合并(堆 || 优先队列)

传送门

首先,把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)。

——代码

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 const int MAXN = 100001;
 8 int n;
 9 int a[MAXN], b[MAXN];
10 
11 struct node
12 {
13     int x, y;
14     node(int x = 0, int y = 0) : x(x), y(y) {}
15 };
16 
17 inline bool operator < (const node v1, const node v2)
18 {
19     return a[v1.x] + b[v1.y] > a[v2.x] + b[v2.y];
20 }
21 
22 std::priority_queue <node> q;
23 
24 inline int read()
25 {
26     int x = 0, f = 1;
27     char ch = getchar();
28     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
29     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
30     return x * f;
31 }
32 
33 int main()
34 {
35     int i;
36     node now;
37     n = read();
38     for(i = 1; i <= n; i++) a[i] = read();
39     for(i = 1; i <= n; i++) b[i] = read();
40     for(i = 1; i <= n; i++) q.push(node(i, 1));
41     for(i = 1; i <= n; i++)
42     {
43         now = q.top();
44         q.pop();
45         printf("%d ", a[now.x] + b[now.y]);
46         if(now.y < n) q.push(node(now.x, now.y + 1));
47     }
48     return 0;
49 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/6900483.html