ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeup——616 | 问题 B: 序列合并

2021-03-03 16:59:21  阅读:229  来源: 互联网

标签:Codeup int sum 616 最小 heap 序列 downAdjust 100010


题目描述

有两个长度都为N的序列A和B,在A和B中各取一个数相加可以得到N2个和,求这N2个和中最小的N个。

输入

第一行一个正整数N(1 <= N <= 100000)。
第二行N个整数Ai,满足Ai <= Ai+1且Ai <= 109
第三行N个整数Bi,满足Bi <= Bi+1且Bi <= 109

输出

输出仅有一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。

样例输入

3
2 6 6
1 4 8

样例输出

3 6 7

思路:可以用堆实现,也可以用优先队列实现,不过说到底实现的原理还是堆,因为优先队列的本质就是堆。
该题中最主要的就是利用了堆中的一个性质,堆顶元素最小或最大,此处使用小堆,即结点的值大于它的子节点。我们先把a中最小的数和b中所有的数加一遍,然后得到数组heap[n],此时再构建出一个小堆,然后把剩下的数相加后和堆顶作比较即可。

#include <iostream>
#include <algorithm>
using namespace std;

int heap[100010], n;

void downAdjust(int low, int high){
	int i = low, j = i * 2;
	while(j <= high){
		if(heap[j+1] > heap[j] && j+1 <= high) j = j + 1;
		if(heap[i] < heap[j]){
			swap(heap[i], heap[j]);
			i = j;
			j = i * 2;
		}else{
			break;
		}
	}
}

void createHeap(){
	for(int i=n/2; i>=1; i--)
		downAdjust(i, n);
}

int main()
{
	int a[100010], b[100010];
	cin >>n;
	for(int i=0; i<n; i++) scanf("%d", &a[i]);
	for(int i=0; i<n; i++) scanf("%d", &b[i]);
	//把a中最小的数和b里所有的数加一遍
	for(int i=0; i<n; i++) heap[i+1] = a[0] + b[i];
	createHeap();	//构建堆
	//剩下的数相加
	for(int i=1; i<n; i++){
		for(int j=0; j<n; j++){
			int sum = a[i] + b [j];
			if(sum < heap[1]){	//如果加数小于堆顶元素
				heap[1] = sum;	//交换值并且向下调整
				downAdjust(1, n);
			}else{
				break;	//剪枝
			}
		}
	}
	sort(heap+1, heap+1+n);	//可以再写一个堆排序算法也可以直接sort
	for(int i=0; i<n; i++) printf("%s%d", i==0?"":" ", heap[i+1]);
	return 0;
}

标签:Codeup,int,sum,616,最小,heap,序列,downAdjust,100010
来源: https://blog.csdn.net/qq_44888152/article/details/114322609

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有