题解 序列合并

题目链接

首先不难想到,最小数的一定是 a1+b1,次小的数是 a1+b2a2+b1 中小的。

得出结论,若 ai+bj 是第 k 小,那么 ai+1+bjai+bj+1 有可能成为第 k+1 小。

这是一个很优秀的性质,这意味着我们可以通过最小值推出次小值,再通过次小值推出次次小值,以此类推。

结合前面,我们已知最小值 a1+b1,那么关键在于如何找出所有可能候选答案中的最小值,这可以用优先队列实现。

注意 a1+b2a2+b1 同时可以推出 a2+b2,所以注意去重,这可以用 set 维护二元组实现。

时间复杂度 O(nlogn).

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
typedef long long LL;
typedef unsigned long long ULL;
LL read() {
LL sum=0,flag=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
return sum*flag;
}
const int N=1e5+10;
int n,a[N],b[N];
struct node {
int x,y;
friend bool operator < (node s1,node s2) {
return a[s1.x]+b[s1.y]>a[s2.x]+b[s2.y];
}
};
priority_queue<node> q;
set<pair<int,int> > f;
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
for(int i=1;i<=n;i++) {
cin>>b[i];
}
int tot=0;
q.push({1,1}); f.insert({1,1});
while(q.size()) {
node t=q.top(); q.pop();
cout<<a[t.x]+b[t.y]<<' ';
tot++;
if(tot==n) break;
if(t.x+1<=n&&f.count({t.x+1,t.y})==0) {
q.push({t.x+1,t.y});
f.insert({t.x+1,t.y});
}
if(t.y+1<=n&&f.count({t.x,t.y+1})==0) {
q.push({t.x,t.y+1});
f.insert({t.x,t.y+1});
}
}
return 0;
}
/*
*/

类似题目:最小函数值,同样是已知最小值,可以推出次小和次次小等的题目。

posted @   2017BeiJiang  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示