洛谷 P1631 序列合并(优先队列)

传送门


解题思路

首先读入a、b数组后,sort一遍(从小到大),然后把a[1]+b[1],a[2]+b[1],a[3]+b[1]……a[n]+b[1]全部加入一个优先队列q(小根堆)。

然后从一到n循环,每一次取出队列中的最小的元素(假设是a[i]+b[j]),输出数值,然后把数值修改为a[i]+b[j+1],存入队列。

为什么呢?

很显然,我们把所有可能的情况列成一张表:

a[1]+b[1],a[2]+b[1],a[3]+b[1],……,a[n]+b[1];

a[1]+b[2],a[2]+b[2],a[3]+b[2],……,a[n]+b[2];

…………………………………………………………;

a[1]+b[n],a[2]+b[n],a[3]+b[n],……,a[n]+b[n]。

很显然,在这张表中,对于每一个数都一定小于它右下方的所有的数。

换一种说法,就是在第[i,j]个数为成为当前最小值时,它右下方的数不可能成为当前最小值。

所以只有在第[i,j]个数成为当前最小值时,把第[i+1][j]加入队列,继续比较。(也就是纵向更新)。

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=100005;
 7 int n,a[maxn],b[maxn];
 8 struct node{
 9     int ans,bb;
10     bool operator < (const node &x)const{
11         return ans>x.ans;
12     }
13 };
14 priority_queue<node> q;
15 int main()
16 {
17     cin>>n;
18     for(int i=1;i<=n;i++) cin>>a[i];
19     for(int i=1;i<=n;i++) cin>>b[i];
20     sort(a+1,a+n+1);
21     sort(b+1,b+n+1);
22     for(int i=1;i<=n;i++){
23         node x;
24         x.ans=a[i]+b[1];
25         x.bb=1;
26         q.push(x);
27     }
28     for(int i=1;i<=n;i++){
29         node now=q.top();
30         q.pop();
31         cout<<now.ans<<" ";
32         now.bb++;
33         now.ans=now.ans+b[now.bb]-b[now.bb-1];
34         q.push(now);
35     }
36     return 0;
37 }

 

posted @ 2019-12-10 23:33  尹昱钦  阅读(210)  评论(0编辑  收藏  举报