1. 程式人生 > >wikioi 1245最小N個和

wikioi 1245最小N個和

題目描述 Description

有兩個長度為 N 的序列 A 和 B,在 A 和 B 中各任取一個數可以得到 N^2 個和,求這N^2 個和中最小的 N個。

輸入描述 Input Description

第一行輸入一個正整數N;第二行N個整數Ai 且Ai≤10^9;第三行N個整數Bi,
且Bi≤10^9

輸出描述 Output Description

輸出僅一行,包含 n 個整數,從小到大輸出這 N個最小的和,相鄰數字之間用
空格隔開。

樣例輸入 Sample Input

5

1 3 2 4 5 
6 3 4 1 7

樣例輸出 Sample Output

2 3 4 4 5

資料範圍及提示 Data Size & Hint

【資料規模】 對於 100%的資料,滿足 1≤N≤100000。

題解:將兩個序列按從小到大排序(實際資料已經有序),對於A[i]和B[j],a[i]+b[j]<a[i]+b[j+1]必然成立。

           於是我們建一個大根堆,儲存最小的N個和。先將A[1]和B的和放入堆中,之後的A[I]和B[J]的和每次與堆頂比較,大於則直接break,小於則置換堆頂即可。輸出時逆序輸出堆中元素

#include<queue>  
#include<cstdio>  
#include<iostream>  
#define MAXN 1000000  
using namespace std;   
priority_queue<int> heap;  
int n;  
int a[MAXN+5],b[MAXN+5],ans[MAXN+5];  
  
int main()  
{  
    scanf("%d",&n);  
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);  
    for (int i=1;i<=n;i++) scanf("%d",&b[i]);  
    for (int i=1;i<=n;i++) heap.push(a[1]+b[i]);  
    for (int i=2;i<=n;i++)  
    {  
        for (int j=1;j<=n;j++)  
        {  
            int now=a[i]+b[j];  
            if (now<heap.top())  
            {  
                heap.pop();  
                heap.push(now);  
            }  
            else break;  
        }  
    }  
    for (int i=1;i<=n;i++)  
    {  
        ans[i]=heap.top();  
        heap.pop();  
    }   
    for (int i=n;i>=1;i--) printf("%d ",ans[i]);  
    return 0;  
}