nyoj 634 万里挑一

万里挑一

时间限制: 3000  ms  |  内存限制: 65535  KB
难度: 5
描述
有两个大小为N的数组A和B,对于每一对(i, j)(0<=i,j<N)都可以得到一个数A[i]+B[j],这样就可以得到N*N个数了,你需要求出前K个大的数,easy?
输入
输入可能会有多组(小于十组),每组3行数据,第一行是两个整数N( N <= 100000 ) 和K(K<=N),接下来2行,每行N个整数,每行的整数都用空格隔开
输出
每组一行,最大的K个数,用空格隔开,从小到大输出。
样例输入
4 3
1 2 3 4
3 6 5 4
样例输出
9 9 10
来源
郑大第六届校赛
 
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int a[100001],b[100001];
struct node {
    int v; int n;
    node(){}
    node(int a,int b):v(a),n(b){}  //不断更新新的队列
    bool operator < (const node& tmp ) const{
    return v< tmp.v;   //使队列维护从大到小的性质
    }
};
bool cmp(int aa,int bb)
{
    return aa > bb;
}
void fun(int *A,int *B,int *C,int n)
{
    priority_queue<node> q;
    int i;
    for( i = 0 ; i < n ; i++)
        q.push(node(A[i]+B[0],0));//先入队列n个数(第一个数是最大的)
    for( i = 0 ; i < n ; i++)
    {
        node tmp = q.top(); q.pop(); //每次最大的数出队列,并保存到数组C中
        C[i] = tmp.v;            //也就是a中,重新赋值节约资源
        int b = tmp.n;            //初始值为0,表示最大数的下标
        if(b<n-1)             //保证下标数至少两个,
        {
            q.push(node(tmp.v - B[b] +B[b+1],b+1));//下标加1,表示第二大的数
            //tmp.v -B[b] + B[b+1] 是小于等于tmp.v的一个数入队列
        }
    }
}
int main()
{
    int k,i,n;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i = 0 ; i < n ; i++)
            scanf("%d",&a[i]);
        for(i = 0 ; i < n ;i++)
            scanf("%d",&b[i]);
        sort(a,a+n,cmp);   
        sort(b,b+n,cmp);  //将a,b都从小到大排列
        fun(a,b,a,k);
        printf("%d",a[k-1]);
        for(i = k -2 ;i>= 0 ;--i)
        printf(" %d",a[i]);
        printf("\n");
    }

}
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值