关于此题P1631 序列合并 的一些总结
题目大意
- 给定两个长度为
的序列,每次选定两个 使得 ,可以合并成 个数的新序列,问此序列中最小的 个数分别是什么。
思路
- 我们可以贪心地思考这道题。要求最大的
个数,那么我们首先对 数组和 数组进行排序,最大的肯定是 ,第二大的只能是 或者 。于是我们发现,可以用优先队列维护这个最大值,当目前优先队列中最大的元素是 时,我们统计答案并pop的同时,把 和 压入优先队列,直到答案有n个为止。同时也需要注意,一个 只能被算一次。
代码
#include<bits/stdc++.h>
using namespace std;
long long t;
const long long N = 2e5 + 10;
long long n,a[N],b[N],ans[N];
struct node {
long long val,i,j;
bool operator < (const node &a) const {
return val > a.val;
}
};
priority_queue<node,vector<node> > q;
unordered_map<int,int> mp[N];
void solve() {
cin >> n;
for(long long i = 1;i <= n;i++) cin >> a[i];
for(long long i = 1;i <= n;i++) cin >> b[i];
sort(a + 1,a + 1 + n);
sort(b + 1,b + 1 + n);
q.push({a[1] + b[1],1,1});
for(long long i = 1;i <= n;i++) {
ans[i] = q.top().val;
long long x = q.top().i,y = q.top().j;
q.pop();
if(y + 1 <= n && !mp[x][y + 1])
q.push({a[x] + b[y + 1],x,y + 1}),mp[x][y + 1] = 1;
if(x + 1 <= n && !mp[x + 1][y])
q.push({a[x + 1] + b[y],x + 1,y}),mp[x + 1][y] = 1;
}
for(long long i = 1;i <= n;i++) cout << ans[i] << ' ';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
t = 1;
while(t--) solve();
return 0;
}