codevs 1245 最小的N個和

來源:互聯網
上載者:User

標籤:namespace   img   序列   技術分享   desc   ane   sample   http   時間複雜度   

1245 最小的N個和 http://codevs.cn/problem/1245/題目描述 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。

堆的基本操作+貪心

堆的基本操作講解,見隨筆:講解——堆http://www.cnblogs.com/TheRoadToTheGold/p/6238795.html

設輸入資料存在數組a[]和b[]中,heap[]為大根堆

為什麼題目要求最小的n個,我們卻要維護大根堆呢?看完以下幾個步驟再說。

1、排序:題目要求輸出最小的n個數,所以先將兩個數組從小到大排序

2、heap[]初始化:因為固定輸出n個數,所以把排序之後的數組a[1]依次與b[]的每一個數相加,和加入heap[]中

3、從a[2]開始枚舉每一個數,如果a中的第i個+b中的第1個(即b中最小的一個)>=heap[1](即堆中最大的元素),那麼結束枚舉。因為a是遞增的,b也是遞增的,後面的相加的和會更大。

    如果a中第i個+b中第j個>=heap[1],那麼枚舉a的下一個,因為b中元素遞增,與同一個a相加後更大;枚舉a的下一個,b從第一個開始,可能會產生更小的。

4、步驟3中,在每加入一個元素之前,都要刪除堆中第一個(即最大的),因為加入的元素一定小於堆中第一個元素。

5、取出堆中的每一個元素,因為是大根堆,而題目要最小的n個,所以倒敘儲存。

6、輸出答案

由此可見為什麼要維護大根堆了吧!利用大根堆的第一個元素可以快速判斷a,b中的數還有沒有枚舉的必要。

有人可能說了,那我維護一個小根堆,不是也能判斷嗎?

的確,也能判斷。

但小根堆中最大的元素尋找時間複雜度為o(n/2),大根堆為O(1)。當然是大根堆快啦。

此處容易有一個理解偏差:認為小根堆中最大的元素就是heap[n],實際不是這樣:

#include<cstdio>#include<algorithm>using namespace std;int n,a[100001],b[100001],heap[100010],s,ans[100001];//s表示heap[]中的元素個數int init()//讀入最佳化 {    int x=0,f=1;char c=getchar();    while(c<‘0‘||c>‘9‘) {if(c==‘-‘) f=-1;c=getchar();}    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}    return x*f;}void insert(int k)//往堆中加入元素k {    s++;    int p=s;    heap[s]=k;    while(p>1&&k>heap[p/2])    {        heap[p]=heap[p/2];        p/=2;    }    heap[p]=k;}void heapify(int t)//維護堆 {    int left=t*2,right=t*2+1;    int maxn=t;    if(left<=s) maxn=heap[maxn]>heap[left] ? maxn:left;    if(right<=s) maxn=heap[maxn]>heap[right] ? maxn:right;    if(maxn!=t)    {        swap(heap[maxn],heap[t]);        heapify(maxn);    }}int get()//取出堆中最大值 {    int top=heap[1];    heap[1]=heap[s];    s--;    heapify(1);    return top;}int main(){    n=init();    for(int i=1;i<=n;i++) a[i]=init();    for(int i=1;i<=n;i++) b[i]=init();    sort(a+1,a+n+1);//排序,對應第1步     sort(b+1,b+n+1);    for(int i=1;i<=n;i++) insert(a[1]+b[i]);//堆得初始化,對應第2步     for(int i=2;i<=n;i++)//對應第3步     {        if(heap[1]<=a[i]+b[1]) break;        for(int j=1;j<=n;j++)        {            if(heap[1]<=a[i]+b[j]) break;            get();//對應第5步             insert(a[i]+b[j]);        }    }    while(s) ans[s]=get();//對應第6步     for(int i=1;i<=n;i++) printf("%d ",ans[i]);//對應第7步 }

剛開始逾時一個點,原因是兩個判斷break的語句沒有加等號。只想著相等的元素也要輸出,卻忽略了判斷的是堆中最大的元素,相不相等無所謂。

逾時的資料:n=10000,然後20000個1,所有的和都是2

codevs 1245 最小的N個和

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.