当前位置: 首页 > news >正文

P1631 序列合并

P1631 序列合并

题目描述

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

输入格式

第一行一个正整数 N N N

第二行 N N N 个整数 A 1 … N A_{1\dots N} A1N

第三行 N N N 个整数 B 1 … N B_{1\dots N} B1N

输出格式

一行 N N N 个整数,从小到大表示这 N N N 个最小的和。

输入输出样例 #1

输入 #1

3
2 6 6
1 4 8

输出 #1

3 6 7

说明/提示

对于 50 % 50\% 50% 的数据, N ≤ 1 0 3 N \le 10^3 N103

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1N105 1 ≤ a i , b i ≤ 1 0 9 1 \le a_i,b_i \le 10^9 1ai,bi109

题解

本题可以将所有序列的和都算出来,然后排序,输出前 N N N 个。

但是这样的时间复杂度为 O ( N 2 ) O(N^2) O(N2),会超时。

所以我们需要优化。

本题的关键在于单调不降

那么显然,对于合并即相加后的序列,其一定是单调不降的。

即:

  • a[1] + b[1] ≤ a[1] + b[2] ≤ a[1] + b[3] ≤ … ≤ a[1] + b[n] ;
  • a[2] + b[1] ≤ a[2] + b[2] ≤ a[2] + b[3] ≤ … ≤ a[2] + b[n] ;

我们可以列表(横向b递增,竖向a递增):

a[1] + b[1]a[1] + b[2]a[1] + b[3]············a[1] + b[n]
a[2] + b[1]a[2] + b[2]a[2] + b[3]············a[2] + b[n]
a[3] + b[1]a[3] + b[2]a[3] + b[3]············a[3] + b[n]
····························································
a[n] + b[1]a[n] + b[2]a[n] + b[3]············a[n] + b[n]

对于整个表,最小的一项一定是a[1] + b[1],次小的一定是a[1] + b[2]或a[2] + b[1],以此类推。

那我们可以用小根堆来维护这个表。

每次取出最小的一项,然后将其下一项加入队列。

这样的时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)

具体来说,根据题意我们需要找出前 N N N 小的和,所以我们需要维护一个大小为 N N N 的优先队列。

那么我们可以先计算出第一行,即a[1] + b[1]到a[1] + b[n],然后将其加入优先队列。

然后我们可以取出队列中的最小值,即a[1] + b[1],然后将其下一项a[2] + b[1]加入队列。

代码实现

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

const int N = 1e5 + 10;

int n;
int a[N],b[N];

struct node{
	int sum;
	int i,j;
	bool operator < (const node& x) const{
		return sum > x.sum;
	}
};

priority_queue<node> heap;

int main(){
	cin >> n;
	for(int i = 1;i <= n;i++) cin >> a[i];
	for(int i = 1;i <= n;i++) cin >> b[i];
	
	for(int i = 1;i <= n;i++){
		heap.push({a[i] + b[1],i,1});
	}
	
	for(int k = 1;k <= n;k++){
		auto t = heap.top();heap.pop();
		int sum = t.sum,i = t.i,j = t.j;
		cout << sum << " ";
		if(j <= n) heap.push({a[i] + b[j + 1],i,j + 1});
	}
	return 0;
}

相关文章:

  • 【OS】操作系统全解
  • 操作系统知识点29
  • Manus邀请码申请全流程指南(2025最新版)——申请Manus体验资格
  • 根据Excel快速生成表的创建以及新增数据记录的sql
  • 批量清空 Excel 文档主题、标记、作者、保存时间、总编辑时间元数据
  • 深入 Python 网络爬虫开发:从入门到实战
  • C# 初学者的系统学习路径与职业规划指南
  • FPGA为何要尽量减少组合逻辑的使用
  • APB-清华联合腾讯等机构推出的分布式长上下文推理框架
  • 图论part4|827. 最大人工岛、127. 单词接龙、463. 岛屿的周长
  • SMT贴片加工核心技术突破与实践
  • 11.anaconda中的jupyter使用、及整合dataspell
  • 3.14-1列表
  • 基于WebRTC与P2P技术,嵌入式视频通话EasyRTC实现智能硬件音视频交互,适配Linux、ARM、RTOS、LiteOS
  • 多线程程序的测试和调试_第11章_《C++并发编程实战》笔记
  • 电脑内存不足怎么办?
  • 游戏引擎学习第155天
  • RK3568 Android13 源码编译
  • soulip属地怎么不是我当前的位置
  • 软件环境安装-通过Docker安装RocketMQ
  • 董军同德国国防部长举行会谈
  • 马上评|这种“维权”已经不算薅羊毛,涉嫌犯罪了
  • 中国—美国经贸合作对接交流会在华盛顿成功举行
  • 著名词作家陈哲逝世,代表作《让世界充满爱》《同一首歌》等
  • 多个侵华日军细菌战部队留守名簿文件首次公布
  • 杭勇已任常州市政协党组成员,此前任常州市委常委、秘书长