1245 最小的N个和

题目描述 Description

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

输入描述 Input Description

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9

输出描述 Output Description

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

样例输入 Sample Input

5

1 3 2 4 5 
6 3 4 1 7

样例输出 Sample Output

2 3 4 4 5

数据范围及提示 Data Size & Hint

【数据规模】 对于 100%的数据,满足 1≤N≤100000。

堆的基本操作+贪心

堆的基本操作讲解,见随笔:讲解——堆http://www.cnblogs.com/TheRoadToTheGold/p/6238795.html

设输入数据存在数组a[]和b[]中,heap[]为大根堆

为什么题目要求最小的n个,我们却要维护大根堆呢?看完以下几个步骤再说。

1、排序:题目要求输出最小的n个数,所以先将两个数组从小到大排序

2、heap[]初始化:因为固定输出n个数,所以把排序之后的数组a[1]依次与b[]的每一个数相加,和加入heap[]中

3、从a[2]开始枚举每一个数,如果a中的第i个+b中的第1个(即b中最小的一个)>=heap[1](即堆中最大的元素),那么结束枚举。因为a是递增的,b也是递增的,后面的相加的和会更大。

如果a中第i个+b中第j个>=heap[1],那么枚举a的下一个,因为b中元素递增,与同一个a相加后更大;枚举a的下一个,b从第一个开始,可能会产生更小的。

4、步骤3中,在每加入一个元素之前,都要删除堆中第一个(即最大的),因为加入的元素一定小于堆中第一个元素。

5、取出堆中的每一个元素,因为是大根堆,而题目要最小的n个,所以倒叙存储。

6、输出答案

由此可见为什么要维护大根堆了吧!利用大根堆的第一个元素可以快速判断a,b中的数还有没有枚举的必要。

有人可能说了,那我维护一个小根堆,不是也能判断吗?

的确,也能判断。

但小根堆中最大的元素查找时间复杂度为o(n/2),大根堆为O(1)。当然是大根堆快啦。

此处容易有一个理解偏差:认为小根堆中最大的元素就是heap[n],实际不是这样:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[],b[],heap[],s,ans[];//s表示heap[]中的元素个数
int init()//读入优化
{
int x=,f=;char c=getchar();
while(c<''||c>'') {if(c=='-') f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void insert(int k)//往堆中加入元素k
{
s++;
int p=s;
heap[s]=k;
while(p>&&k>heap[p/])
{
heap[p]=heap[p/];
p/=;
}
heap[p]=k;
}
void heapify(int t)//维护堆
{
int left=t*,right=t*+;
int maxn=t;
if(left<=s) maxn=heap[maxn]>heap[left] ? maxn:left;
if(right<=s) maxn=heap[maxn]>heap[right] ? maxn:right;
if(maxn!=t)
{
swap(heap[maxn],heap[t]);
heapify(maxn);
}
}
int get()//取出堆中最大值
{
int top=heap[];
heap[]=heap[s];
s--;
heapify();
return top;
}
int main()
{
n=init();
for(int i=;i<=n;i++) a[i]=init();
for(int i=;i<=n;i++) b[i]=init();
sort(a+,a+n+);//排序,对应第1步
sort(b+,b+n+);
for(int i=;i<=n;i++) insert(a[]+b[i]);//堆得初始化,对应第2步
for(int i=;i<=n;i++)//对应第3步
{
if(heap[]<=a[i]+b[]) break;
for(int j=;j<=n;j++)
{
if(heap[]<=a[i]+b[j]) break;
get();//对应第5步
insert(a[i]+b[j]);
}
}
while(s) ans[s]=get();//对应第6步
for(int i=;i<=n;i++) printf("%d ",ans[i]);//对应第7步
}

刚开始超时一个点,原因是两个判断break的语句没有加等号。只想着相等的元素也要输出,却忽略了判断的是堆中最大的元素,相不相等无所谓。

超时的数据:n=10000,然后20000个1,所有的和都是2

codevs 1245 最小的N个和的更多相关文章

  1. CODEVS 1245 最小的N个和 堆+排序

    原题链接 http://codevs.cn/problem/1245/ 题目描述 Description 有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求 ...

  2. AC日记——最小的N个和 codevs 1245

    1245 最小的N个和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 有两个长度为 N ...

  3. 最小的N个和(codevs 1245)

    1245 最小的N个和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 有两个长度为 N ...

  4. 1245 最小的N个和

    1245 最小的N个和 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond         题目描述 Description 有两个长度为 N 的序列 A 和 B, ...

  5. 1245 最小的N个和(前k小ai+bi)

    1245 最小的N个和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 有两个长度为 N ...

  6. code vs 1245 最小的N个和

    1245 最小的N个和  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 有两个长度为 N 的序列 A ...

  7. Codevs No.1245 最小的N个和

    2016-05-31 18:52:15 题目链接: 最小的N个和 Codevs No.1245 题目大意: 给两个等长数列,各取一个数求和,找到最小的N组 解法: 堆优化的大暴力 直接枚举所有可能在最 ...

  8. codevs 2796 最小完全图

    2796 最小完全图 http://codevs.cn/problem/2796/  时间限制: 1 s  空间限制: 128000 KB     题目描述 Description 若一个图的每一对不 ...

  9. Codevs 1904 最小路径覆盖问题

    1904 最小路径覆盖问题 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 大师 Master 传送门 题目描述 Description 给定有向图G=(V,E).设P 是G 的一个 ...

随机推荐

  1. HTTP Method详细解读(`GET` `HEAD` `POST` `OPTIONS` `PUT` `DELETE` `TRACE` `CONNECT`)

    前言 HTTP Method的历史: HTTP 0.9 这个版本只有GET方法 HTTP 1.0 这个版本有GET HEAD POST这三个方法 HTTP 1.1 这个版本是当前版本,包含GET HE ...

  2. 后台管理UI的选择

    最近要做一个企业的OA系统,以前一直使用EasyUI,一切都好,但感觉有点土了,想换成现在流行的Bootstrap为基础的后台UI风格,想满足的条件应该达到如下几个: 1.美观.大方.简洁 2.兼容I ...

  3. 用php实现一个简单的链式操作

    最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...

  4. AngularJs学习笔记(制作留言板)

    原文地址:http://www.jmingzi.cn/?post=13 初学Anjularjs两天了,一边学一边写的留言板,只有一级回复嵌套.演示地址 这里总结一下学习的过程和笔记.另外,看看这篇文章 ...

  5. 认识W3C标准盒子模型,理解外边距叠加

    概述: 注:加粗斜体字是非常重要的概念,决定着你是不是能看懂那句话,所以不懂的请一定要搜索一下. 页面上的每个元素,都在一个矩形框里.   每个矩形框都是一个盒模型.   每个盒模型都由内容区域(co ...

  6. Scrapy:为spider指定pipeline

    当一个Scrapy项目中有多个spider去爬取多个网站时,往往需要多个pipeline,这时就需要为每个spider指定其对应的pipeline. [通过程序来运行spider],可以通过修改配置s ...

  7. Rafy 框架 - 使用 SqlTree 查询

    本文介绍如何使用 Rafy 框架中的 Sql Tree 查询: 除了开发者常用的 Linq 查询,Rafy 框架还提供了 Sql 语法树的方式来进行查询. 这种查询方式下,开发者不需要直接编写真正的 ...

  8. Struts2框架简介和示例

    struts2框架 Struts2是java web的框架,在Java Web开发中,表示层框架,其核心是通过扩展Servlet来帮助处理http请求. Struct2的基本流程 Struct2的框架 ...

  9. JS高程4.变量,作用域和内存问题(2)执行环境及作用域

    1.执行环境:执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为, 每个执行环境都有一个与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中. 2.全局执行环境: 最外围的 ...

  10. 在Android中,使用Kotlin的 API请求简易方法

    原文标题:API request in Android the easy way using Kotlin 原文链接:http://antonioleiva.com/api-request-kotli ...