zoukankan      html  css  js  c++  java
  • 洛谷1631 序列合并

    题目描述

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

    输入输出格式

    输入格式:
    第一行一个正整数N;

    第二行N个整数Ai,满足Ai<=Ai+1且Ai<=10^9;

    第三行N个整数Bi, 满足Bi<=Bi+1且Bi<=10^9.

    【数据规模】

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

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

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

    输入输出样例

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

    思路是先把第二组的第一个数和第一组所有数相加,建立一个大根堆,再把第二组第二个数与第一组所有数相加,如果小于堆顶就把堆顶换了,维护堆,如果大则第二组第三个数,以此类推,直到第二组第n个数与第一组第一个数相加小于堆顶,则输出堆。

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=100005;
    bool flag; 
    int n,a[MAXN],b[MAXN],f[MAXN],cnt,k=1,ff[MAXN];
    void pus(int x){
        cnt++;f[cnt]=x;
        int now=cnt;
        while(now>1){
            if(f[now]<f[now/2]) break;
            swap(f[now],f[now/2]);
            now/=2;
        }
    }
    void del(){
        int now=1;
        while(now*2<=cnt){
            int tp=now*2;
            if(f[tp]<f[tp+1] && tp<cnt) tp++;
            if(f[tp]<f[now])  break;
            swap(f[tp],f[now]);
            now=tp;
        }
    }
    int main(){
        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++)   pus(b[1]+a[i]);
        while(!flag && k<n){
            k++;
            for(int i=1;i<=n;i++){
                if(i==1 && b[k]+a[i]>f[1]){flag=1;break;}
                if(b[k]+a[i]>=f[1]) break;
                f[1]=b[k]+a[i];
                del();
            }
        }
        sort(f+1,f+1+n);
        for(int i=1;i<=n;i++)
            printf("%d ",f[i]);
        return 0;
    }

    还有一种简单写法,思路一样

    #include<bits/stdc++.h>
    int a[100010],b[100010],num[100010],n;
    int main() {
        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++) num[i]=1;
        for(int i=1; i<=n; i++) {
            int temp=1;
            int rmin=1000000000;
            for (int j=1; j<=n; j++) {
                if(a[j]+b[num[j]]<rmin) {
                    temp=j;
                    rmin=a[j]+b[num[j]];
                }
                if(a[j]+b[num[n]]>rmin) {
                    num[temp]++;
                    break;
                }
            }
            printf("%d ",rmin);
        }
        return 0;
    }
  • 相关阅读:
    Python 爬虫
    Web 前端编程运维必备
    Docker 运维高级应用管理
    Python 运维之路
    Linux 运维之路
    8086汇编 中断
    8086汇编 rep 指令
    8086汇编 cmp 指令
    8089汇编 标志寄存器
    8086汇编 call 指令
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677230.html
Copyright © 2011-2022 走看看