题目描述

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

输入输出格式

输入格式:

第一行一个正整数N;

第二行N个整数A_iAi​, 满足A_i\le A_{i+1}Ai​≤Ai+1​且A_i\le 10^9Ai​≤109;

第三行N个整数B_iBi​, 满足B_i\le B_{i+1}Bi​≤Bi+1​且B_i\le 10^9Bi​≤109.

【数据规模】

对于50%的数据中,满足1<=N<=1000;

对于100%的数据中,满足1<=N<=100000。

输出格式:

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

输入输出样例

输入样例#1: 复制

  1. 3
  2. 2 6 6
  3. 1 4 8
输出样例#1: 复制

  1. 3 6 7
  2.  
  3. 思路:朴素做法的复杂度不可取,那么取完前3N个肯定有前N个的答案,代码如下:
  1. const int maxm = ;
  2.  
  3. int a[maxm], b[maxm];
  4.  
  5. int main() {
  6. int n;
  7. scanf("%d", &n);
  8. for (int i = ; i < n; ++i)
  9. scanf("%d", &a[i]);
  10. for (int i = ; i < n; ++i)
  11. scanf("%d", &b[i]);
  12. priority_queue<int, vector<int>, greater<int>> q;
  13. int l = , r = ;
  14. q.push(a[l] + b[r]);
  15. while(q.size() <= *n) {
  16. if(a[l] <= b[r]) {
  17. l++;
  18. if(l >= n)
  19. break;
  20. for (int i = ; i <= r; ++i)
  21. q.push(a[l] + b[i]);
  22. } else {
  23. r++;
  24. if(r >= n)
  25. break;
  26. for (int i = ; i <= l; ++i)
  27. q.push(a[i] + b[r]);
  28. }
  29. }
  30. for (int i = ;i < n; ++i) {
  31. if(i)
  32. printf(" ");
  33. printf("%d", q.top());
  34. q.pop();
  35. }
  36. return ;
  37. }

 看完别人的解析后,懂了一种新的做法,图示:

  a1 a2 a3 a4 a5
b1          
b2          
b3          
b4          
b5          

此时N = 5, 若a3+b2是前N小,那么从a1+b1前面都是前N小,但其前面已经有N个了,则a3+b2不可能是前N小,即:(i-1)*(j-1) > N的点不可能产生贡献,代码如下:

  1. const int maxm = ;
  2.  
  3. int a[maxm], b[maxm];
  4.  
  5. int main() {
  6. int n;
  7. scanf("%d", &n);
  8. for (int i = ; i < n; ++i)
  9. scanf("%d", &a[i]);
  10. for (int i = ; i < n; ++i)
  11. scanf("%d", &b[i]);
  12. priority_queue<int, vector<int>, greater<int>> q;
  13. for(int i = ; i < n; ++i) {
  14. for (int j = ; j < n; ++j) {
  15. if(i * j > n)
  16. break;
  17. q.push(a[i] + b[j]);
  18. }
  19. }
  20. for (int i = ;i < n; ++i) {
  21. if(i)
  22. printf(" ");
  23. printf("%d", q.top());
  24. q.pop();
  25. }
  26. return ;
  27. }

还有一种通用的合并队列最小值做法,因为a[1]+b[1]<=a[2]+b[1]<= ······ 这时候将所有的含有b[1]的压入队列,将最小的出队,例如,此时出队的是a[5]+b[1],那么下次入队的就是a[5]+b[2],且此时的a[5]+b[2]比任何还未入队的元素都大,循环往复找到N个即可,代码如下:

  1. const int maxm = ;
  2.  
  3. struct Node{
  4. int sum, ia, ib;
  5. Node(int _sum, int _ia, int _ib):sum(_sum), ia(_ia), ib(_ib) {}
  6. bool operator < (const Node &a)const {
  7. return a.sum < sum;
  8. }
  9. };
  10.  
  11. int a[maxm], b[maxm];
  12.  
  13. int main() {
  14. int n;
  15. scanf("%d", &n);
  16. for (int i = ; i < n; ++i)
  17. scanf("%d", &a[i]);
  18. for (int i = ; i < n; ++i)
  19. scanf("%d", &b[i]);
  20. priority_queue<Node> q;
  21. for (int i = ; i < n; ++i) {
  22. q.push(Node(a[i] + b[], i, ));
  23. }
  24. while(n--) {
  25. Node tmp = q.top();
  26. q.pop();
  27. printf("%d ", tmp.sum);
  28. q.push(Node(a[tmp.ia] + b[tmp.ib + ], tmp.ia, tmp.ib + ));
  29. }
  30. return ;
  31. }

Day1-Luogu-1631的更多相关文章

  1. luogu 1631 序列合并

    priority_queue的使用,注意 a[1]+b[1],a[1]+b[2],a[1]+b[3],a[1]+b[4].......a[1]+b[n] a[2]+b[1]......... .. a ...

  2. [LUOGU] NOIP提高组模拟赛Day1

    题外话:以Ingress为题材出的比赛好评,绿军好评 T1 考虑枚举第\(i\)个人作为左边必选的一个人,那左边剩余\(i-1\)个人,选法就是\(2^{i-1}\),也就是可以任意选或不选,右侧剩余 ...

  3. Luogu P1600[NOIP2016]day1 T2天天爱跑步

    号称是noip2016最恶心的题 基本上用了一天来搞明白+给sy讲明白(可能还没讲明白 具体思路是真的不想写了(快吐了 如果要看,参见洛谷P1600 天天爱跑步--题解 虽然这样不好但我真的不想写了 ...

  4. LUOGU NOIP 2018 模拟赛 DAY1

    T1 传送门 解题思路 这似乎是小学数学知识???mod 9就相当于各位之和mod 9,打表求了个逆元,等差数列求和公式就行了. #include<iostream> #include&l ...

  5. luogu P4798 [CEOI2015 Day1]卡尔文球锦标赛 dp 数位dp

    LINK:卡尔文球锦标赛 可以先思考一下合法的序列长什么样子. 可以发现后面的选手可以使用前面出现的编号也可以直接自己新建一个队. 其实有在任意时刻i 序列的mex>max.即要其前缀子序列中1 ...

  6. noip2011提高组day1+day2解题报告

    Day1 T1铺地毯https://www.luogu.org/problem/show?pid=1003 [题目分析] 全部读入以后从最后一个往前找,找到一个矩形的范围覆盖了这个点,那这个矩形就是最 ...

  7. 【NOIP2016 Day1 T2】天天爱跑步

    题目传送门:https://www.luogu.org/problemnew/show/P1600 感觉这两天在处理边界问题上有点神志不清......为了从80的暴力变成100,花了整整一个下午+一个 ...

  8. NOI Day1线上同步赛梦游记

    Preface 第一次体验NOI,虽然不是正式选手,但是打打同步赛还是挺涨姿势的,也算是体验了一把. Day1很爆炸,一方面是NOI题目的难度高于自身的水平,另一方面也出现了比较大的失误,T1一个数组 ...

  9. 3728 联合权值[NOIP 2014 Day1 T2]

    来源:NOIP2014 Day1 T2 OJ链接: http://codevs.cn/problem/3728/ https://www.luogu.org/problemnew/show/P1351 ...

  10. [luogu]P1600 天天爱跑步[LCA]

    [luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...

随机推荐

  1. Docker for YApi--一键部署YApi

    获取YApi镜像$ docker pull mrjin/yapi:latest 注意:本仓库目前只支持安装,暂不支持升级,请知晓.如需升级请备份mongoDB内的数据. docker-compose ...

  2. Promise解决回调地狱(多层调用问题)

    Promise # Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息:从本意上讲,它是承诺,承诺它过一段时间会给你一个结果.promise有三 ...

  3. 到底是哪个“O”管理内部人员风险?

    导读 俗话说,家和万事兴.与之相对的,家不睦则必自败.同理,如果缺乏明确的领导,内部人员风险管理项目或内部人威胁项目 (ITP) 也将走向失败. 俗话说,家和万事兴.与之相对的,家不睦则必自败.同理, ...

  4. centos无法启动之fstab

    你可能由于对磁盘管理,修改了/etc/fstab文件,进行自动挂载,但是卸载磁盘后,忘记修改/etc/fstab文件,导致了如下启动linux错误,开启进入紧急模式 error getting aut ...

  5. springboot 打包成jar

    1.pom.xml配置 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins< ...

  6. Python - unittest打印成功信息

    参考 https://stackoverflow.com/questions/36834677/print-success-messages-for-asserts-in-python 总结 clas ...

  7. 【协作式原创】查漏补缺之Golang中mutex源码实现(预备知识)

    预备知识 CAS机制 1. 是什么 参考附录3 CAS 是项乐观锁技术,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是 ...

  8. 吴裕雄--天生自然ORACLE数据库学习笔记:Oracle数据备份与恢复

    run{ allocate channel ch_1 device type disk format = 'd:\oraclebf\%u_%c.bak'; backup tablespace syst ...

  9. C 语言入门---第十一章---C语言重要知识点补充

    ====C语言typedef 的用法==== 1. C语言允许为一个数据类型起一个新的别名,就像给人起绰号一样. typedef OldName newName; typedef 和 #define ...

  10. python爬虫(九) requests库之post请求

    1.方法: response=requests.post("https://www.baidu.com/s",data=data) 2.拉勾网职位信息获取 因为拉勾网设置了反爬虫机 ...