【ybt高效进阶4-1-2】【luogu P1631】序列合并

序列合并

题目链接:ybt高效进阶4-1-2 / luogu P1631

题目大意

有两个长度为 N 的序列,然后两个序列中各任取一个加在一起可以得到长度为 N*N 的序列,问你这个新序列中的最小的前 N 个。

思路

我们考虑因为是相加,我们让加的两个都尽可能小。

那我们就固定一边从小到大,先选小的,再选大的。
但是另一边呢?

我们考虑用这样的一种方法:
每个数一开始都跟另一边的第一个(也就是最小的)对应,然后得出的每个数放进堆里面。
每次你就找到堆中最小的数,然后输出它,把它弹出,然后我们在插入数的时候记录它是那一边的哪个数,然后就插入这个数下一个对应的点。

说的不太清楚,可以看看代码。

代码

#include<queue>
#include<cstdio>

using namespace std;

int n, a[100001], b[100001];
int now[100001];
priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;

int main() {
    
    
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
	
	for (int i = 1; i <= n; i++) {
    
    
		now[i] = 1;//记录这一边的这个数跟另一边匹配到第几个
		q.push(make_pair(a[i] + b[1], i));
	}
	
	for (int i = 1; i <= n; i++) {
    
    
		printf("%d ", q.top().first);
		
		int tmp = q.top().second;
		q.pop();
		
		now[tmp]++;//匹配下一个
		if (now[tmp] > n) continue;
		q.push(make_pair(a[tmp] + b[now[tmp]], tmp));
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43346722/article/details/114680313