关于此题P1631 序列合并 的一些总结

传送门

题目大意

  • 给定两个长度为N的序列,每次选定两个i,j使得a[i]+b[j],可以合并成N2个数的新序列,问此序列中最小的N个数分别是什么。

思路

  • 我们可以贪心地思考这道题。要求最大的N个数,那么我们首先对a数组和b数组进行排序,最大的肯定是a[1]+b[1],第二大的只能是a[1]+b[2]或者a[2]+b[1]。于是我们发现,可以用优先队列维护这个最大值,当目前优先队列中最大的元素是a[i]+b[j]时,我们统计答案并pop的同时,把a[i+1]+b[j]a[i]+b[j+1]压入优先队列,直到答案有n个为止。同时也需要注意,一个(i,j)只能被算一次。

代码

#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;
}
posted @   孤枕  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
女人的武器不是眼泪,而是微笑。