中位數,堆,優先隊列

題目描述

給出一個長度爲 NNN 的非負整數序列 AiA_iAi ,對於所有 1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21k(N+1)/2 ,輸出 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,,A2k1 的中位數。即前 1,3,5,…1,3,5,…1,3,5, 個數的中位數。

輸入輸出格式

輸入格式:

111 行爲一個正整數 NNN ,表示了序列長度。

222 行包含 NNN 個非負整數 Ai(Ai≤109)A_i (A_i ≤ 10^9)Ai(Ai109)

輸出格式:

(N+1)/2(N + 1) / 2(N+1)/2 行,第 iii 行爲 A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1,A3,,A2k1 的中位數。

輸入輸出樣例

輸入樣例#1:複製
7
1 3 5 7 9 11 6
輸出樣例#1:複製
1
3
5
6

說明

對於 20%20\%20% 的數據, N≤100N ≤ 100N100

對於 40%40\%40% 的數據, N≤3000N ≤ 3000N3000

對於 100%100\%100% 的數據, N≤100000N ≤ 100000N100000

分析;

思維比較巧妙

1。兩個堆,借鑑,max,min;

2。輸入第一個數字後,每輸入兩個數字要輸出一次,所以用bool標記,初始爲1,從第二個數字開始,每輸入一個改變一次;

a1a2a3
101

當bool爲真時就意味着要輸出了;

3。堆只能輸出堆頂的數字,所以要把中位數放在堆頂;

min中從小到大排,優先隊列默認從大到小,所以入隊時爲push(-a);則相當於從小到大;

如果比min中最小的大就放到max中去;

如果兩個堆相差2說明較長堆中第二個數是中位數,這時要轉移top數到另一個堆,以便輸入新數據,得到新中位數;

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int main()
{
    int n,a;
    scanf("%d",&n);
    priority_queue<int>max,min;
    scanf("%d",&a);printf("%d\n",a);
    min.push(-a);
    bool no=1;
    for(int i=1;i<n;i++)
    {
        no=1-no;
        scanf("%d",&a);
        if(a>=-min.top())min.push(-a);else max.push(a);
        if(min.size()-max.size()==2){max.push(-min.top()),min.pop();}
        else if(max.size()-min.size()==2){min.push(-max.top()),max.pop();}
        if(no)
        {
            if(min.size()>max.size())printf("%d\n",-min.top());
            else printf("%d\n",max.top());
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章