【luogu】p1631 序列合并

题目链接www

仔细观察我们会发现以下规律

固定 A[i], 每 n 个和都是有序的:

A[1] + B[1], A[1] + B[2], …, A[1] + B[n]

A[2] + B[1], A[2] + B[2], …, A[2] + B[n]

A[n] + B[1], A[n] + B[2], …, A[n] + B[n]

分析

也就是说我们每次只需要考虑每一行的第一个还未计入答案的

我们建立一个小根堆,第一次先把每一行第一个数加入堆中

堆中记录加入的数 和这个数所在的行

每一次我们输出堆顶,并且找到堆顶的那个数所在的那一行,将堆顶后一个数加入堆中(可以用flag数组记录每一行考虑到了第几个数)

为了让代码更加简洁

我们可以使用stl中的prority_queue,将它转换为小根堆。

pair类型来存储堆中每一个元素的数值,以及所在行

code

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
long long a[100001],b[100001];
priority_queue<pair<long long,int> > qwq;//第一个存这个数的值 第二个存它在第几行
int read(){
    int a = 0,f = 0;char p = getchar();
    while(!isdigit(p)){f|=p=='-0';p = getchar();}
    while(isdigit(p)){a = (a<<3)+(a<<1)+(p^48);p = getchar();}
    return f?-a:a;
}
int flag[100001];//记录每一行到了第几个
int main(){
    int n;
    n = read();
    for(int i = 1;i <= n; i++)
        a[i] = read();
    for(int i = 1;i <= n;i++)b[i] = read();
    for(int i = 1;i <= n;i ++){
        qwq.push(make_pair(-a[i]-b[1],i));
        flag[i] = 1;
    }
    while(n--){
        cout<<-qwq.top().first<<" ";
        int x = qwq.top().second;//在第x行
        qwq.pop();
        flag[x]++;
        long long sum = a[x]+b[flag[x]];
        qwq.push(make_pair(-sum,x));
    }
    return 0;

}

猜你喜欢

转载自www.cnblogs.com/huixinxinw/p/12242330.html