2013多校第四场 B题

题意:

  两个都含有N个元素的数组a,b, 求 a[i]+b[j] ( i , j < N ) 的前 M个最小值(M < N)

解题思路:

  假定a,b数组都有序,则我们有下面的结论:

  a_1 + b_1 <= a_1 + b_2 <= ... <= a_1 + b_n

  a_2 + b_1 <= a_2 + b_2 <= ... <= a_2 + b_n

  ...

  a_n + b_1 <= a_n + b_2 <= ... <= a_n + b_n

  那么我们就可以得出一个 N*N 的矩阵.如下形式

  A(1,1), A(1,2), ..., A(1,n)

  A(2,1), A(2,2), ... ,A(2,n)

  ...

  A(n,1), A(n,2), ... ,A(n,n)

  我们知道,第一个最小的必定是 A(1,1), 

  而且. 从 A(1,1) 位置往下(A(2,1)) 或者 往右(A(1,2)), 其值必定增大.

  但是我们又不知道 A(1,2) 与 A(2,1) 之间的关系.

  不过, 我们可以想到:

    若第k小的数是 A(i,j), 则第 k+1小的数可能是A(i+1,j)与A(i,j+1) 之间的数.

    因为还有可能是在 其他的 A( a,b ) 的下或者右中..

  又因为 我们只需要取前 M <= N 个数.所以我们使用一个容器,让里头保存N个数.

  每次从容器中取出一个最值( A(a,b) ), 则再将其下方( A(a+1,b) ),与右边( A(a,b+1) ) 的值放入容器中.  

  这个容器我们可以选 堆/优先队列: 

  直接用 C++的STL.  priority_queue< node, vector<node>, compare >  详细用法请百度.

编码细节:

  我们可以预处理把 A(1,1), A(1,2), ...,A(1,n) 这N个数放到堆中, 每次取出最小的A(a,b)时,

  则只需要将 A(a+1,b) 加入到堆即可. 因为 A(a,b+1)已经在堆中了. 

  这样.始终维护着堆中包含N个元素. 当输出满足M个了就结束即可.

算法时间复杂度:

  优先队列的 插入与删除操作都是 Log(N). 总共N个元素.

  则总体时间复杂度:  NlogN 

View Code
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 4e5+10;

int a[N], b[N], res[N];
int n, m;
struct Node{
    int x, y, v;
    bool operator < (const Node &tmp) const{
        return v > tmp.v;    
    }
}node;
priority_queue<Node> Q;

int main(){
    freopen("1002.in","r",stdin);
    freopen("test.out","w",stdout);
    while( scanf("%d%d", &n, &m) != EOF){
        int cnt = 0;
        for(int i = 0; i < n; i++) scanf("%d", &a[i]);
        for(int i = 0; i < n; i++) scanf("%d", &b[i]);
        sort( a, a+n );
        sort( b, b+n );
        while( !Q.empty() ) Q.pop();
        for(int i = 0; i < n; i++){
            node.x = 0; node.y = i; node.v = a[0]+b[i];
            Q.push(node);
        }
        for(int i = 0; i < m; i++){
            node = Q.top(); Q.pop();
            printf("%d\n", node.v );
            node.x++; 
            node.v = a[ node.x ] + b[ node.y ];
            Q.push( node );
        }    
    }
    return 0;
}

 

posted @ 2013-04-28 16:10  yefeng1627  阅读(150)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor