2269: minval(优先队列)

2269: minval
时间限制: 3 Sec  内存限制: 256 MB
提交: 621  解决: 62
[提交][状态][讨论版][命题人:外部导入]
题目描述

有两个长度为N的序列A和B,在A和B中各任取一个数相加可以得到N2个和,求这N2个和中最小的N个。 

输入
第一行输入一个正整数N(1<=N<=100000); 

第二行N个整数Ai且Ai<=109;第三行N个整数Bi且Bi<=109。 

输出
输出仅一行,包含n个整数,从小到大输出这n个最小的和,相邻数字之间用空格隔开。 

样例输入
5
1 3 2 4 5
6 3 4 1 7

样例输出

2 3 4 4 5

按大白书上的原理,先对两个数组排序,用一个二元组来标记两个数的和,和b数组的当前位置,放入优先队列中。每一次把最小的取出来,再把最小和s-b[i]+b[i+1]放入队列,循环n次就可以了;


#include<stack>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#define maxn 5000005
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define inf 0x3f3f3f
using namespace std;
ll a[maxn];
ll b[maxn];
ll c[maxn];
struct node{
    ll s,b;
    node(ll s,ll b):s(s),b(b){}
    bool operator <(const node& rhs)const{
        return s>rhs.s;
    }
};
void m(ll *A,ll *B,ll *C,int n){
    priority_queue<node>q;
    for(int i=0;i<n;i++){
        q.push(node(A[i]+B[0],0));
    }
    for(int i=0;i<n;i++){
        node d=q.top();q.pop();
        C[i]=d.s;
        int b=d.b;
        if(b+1<n)q.push(node(d.s-B[b]+B[b+1],b+1));
    }
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++)scanf("%lld",&a[i]);
        for(int j=0;j<n;j++)scanf("%lld",&b[j]);
        sort(a,a+n);
        sort(b,b+n);
        m(a,b,c,n);
        for(int i=0;i<n;i++){
            cout<<c[i]<<" ";
        }
    }
}





posted @ 2018-04-21 19:22  _大美  阅读(142)  评论(0编辑  收藏  举报