【luogu】p1631 序列合并
仔细观察我们会发现以下规律
固定 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;
}