zoukankan      html  css  js  c++  java
  • P1631 序列合并

    题目大意

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

    输入格式

    • 第一行一个正整数N;
    • 第二行有N个整数 表示(a_1)...(a_n) 且保证(a_i <= a_{i+1})
    • 第二行有N个整数 表示(b_1)...(b_n) 且保证(b_i <= b_{i+1})

    输出格式

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

    样例

    3
    2 6 6
    1 4 8
    
    3 6 7
    

    算法分析

    • 这个题不难 但是有一种很好的贪心思想值得我们学习
    • 首先看到这个题 暴力的思想很容易想出来 (N^2)暴力嘛 但是如何更快呢?
    • 首先我们想这样一个问题 如果我们要求的是最小的一个数 那怎么求呢? 没人会把所有的和都求出来然后sort吧 没错,最小的一个数肯定是(a_1) + (b_1)
    • 那么我们的前N大可不可以用同样的贪心思想求解呢???
      如果有这样一个表格表示a[i] + b[j]的和 那么就有
    (b_1) (b_2) (b_3)
    (a_1) 3 6 10
    (a_2) 7 10 14
    (a_3) 7 10 14
    • 通过这个表格显然会有一个很easy的规律:
      每个表格内的位置都比它右边和它下边的数要小
    • 这也很容易证明 对于它右边的数 因为(b_{j+1}) >= (b_j) 而加上同一个(a_i) 同理向下也是一样
    • 所以对于这个性质我们可以维护一个单调队列 首先把第一行的所有数扔进去 然后在里面找出最小值(显然所有数中的最小值就是第一个)
    • 然后将这个数下面的那个数加进队列(因为一开始是加入了一行)通过N次这样的取出与加入操作 可以求出前N小

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    int a[maxn],b[maxn];
    
    struct node{
    	int a,b,v;
    	node(int ta,int tb,int tv){
    		a = ta;
    		b = tb;
    		v = tv;
    	}
    	bool operator <(const node &A)const{
    		return v > A.v;
    	}
    };
    
    priority_queue<node> q;
    
    int main(){
    	int n;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){
    		q.push(node(i,1,a[i] + b[1]));
    	}
    	for(int i = 1;i <= n;++i){
    		int ta = q.top().a;
    		int tb = q.top().b;
    		int tv = q.top().v;
    		q.pop();
    		printf("%d ",tv);
    		q.push(node(ta,tb + 1,a[ta] + b[tb + 1]));
    	}
    	return 0;
    }
    
    如初见 与初见
  • 相关阅读:
    php排序算法-冒泡排序
    Mac安装java JDK
    mysql索引简单记录一下
    Mac 通过 pecl安装 redis 扩展
    Mac通过pecl安装swool时遇到的坑(root + openssl)
    php获取两个日期的之间的日期信息,返回数组
    2021.4.9训练
    王道数据结构代码:双向链表的操作
    王道数据结构代码:单链表的操作
    PTA 7-1 大炮打蚊子 (15 分)
  • 原文地址:https://www.cnblogs.com/HISKrrr/p/13369922.html
Copyright © 2011-2022 走看看