解题思路:
首先,把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 }