P1631 序列合并 思维 堆优化
P1631 序列合并 思维 堆优化
题意
有两个长度都是\(N\)的序列\(A\)和\(B\),在\(A,B\)中各取一个数相加共可以得到\(N^2\)个和,求出这\(N ^ 2\)个和中最小的\(N\)的
\[A_i \leq A_{i+1},A_i \leq 10^9\\
B_i \leq B_{i+1},B_i\leq 10^9\\
N\leq 10^5
\]
分析
注意到问题可以转化为在一个\(N \times N\)的矩阵中选择\(N\)个最小的元素
注意到这个矩阵的特点,从左到右以及从上到下都是递增的,因此每次选择实际上都是只在有限个数中选取
维护一列数,若其中某个数是最小的则弹出,加入这个数的下一列数
显然维护的第一列数是可以是第一列
因此可以用堆来维护
代码用用负数push,可以不用写比较函数
时间复杂度\(O(nlogn)\)
代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
ull readull(){
ull x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}
int readint(){
int x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}
#define pii pair<int,int>
#define fi first
#define se second
const int maxn = 1e5 + 5;
int a[maxn];
int b[maxn];
int cur[maxn];
priority_queue<pii> q;
int main(){
int n = readint();
for(int i = 1;i <= n;i++)
a[i] = readint();
for(int i = 1;i <= n;i++)
b[i] = readint();
for(int i = 1;i <= n;i++)
q.push(make_pair(-(a[1] + b[i]),i));
for(int i = 1;i <= n;i++){
pii now = q.top();
cur[now.se]++;
q.pop();
q.push(make_pair(-(a[1 + cur[now.se]] + b[now.se]),now.se));
printf("%d ",-now.fi);
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步