1. 程式人生 > >【洛谷】【堆】P1168 中位數

【洛谷】【堆】P1168 中位數

算法分析 相差 位數 class main family style 正整數 include

【題目描述:】

給出一個長度為N的非負整數序列A[i],對於所有1 ≤ k ≤ (N + 1) / 2,輸出A[1], A[3], …, A[2k - 1]的中位數。即前1,3,5,……個數的中位數。

【輸入格式:】

輸入文件median.in的第1行為一個正整數N,表示了序列長度。

第2行包含N個非負整數A[i] (A[i] ≤ 10^9)。

【輸出格式:】

輸出文件median.out包含(N + 1) / 2行,第i行為A[1], A[3], …, A[2i – 1]的中位數。

技術分享圖片
輸入樣例#17
1 3 5 7 9 11 6
輸出樣例#11
3
5
6
輸入輸出樣例

【算法分析:】

開一個大根堆一個小根堆,

小根堆裏放大數,大根堆裏放小數,保證兩個堆的大小差值小於等於1

這樣最後元素個數多的堆的堆頂就是中位數。

讀入數列a,把a1 push進大根堆

對於a中的每一個數:

  如果比大根堆的堆頂大就放進小根堆

  否則放進大根堆

為了保證兩個堆中的元素個數相差小於等於1

  不停地把元素多的堆的堆頂push到元素少的堆裏去

最後元素多的堆的堆頂便是數列的中位數

【代碼:】

 1 //中位數
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<queue>
 6
#include<cmath> 7 using namespace std; 8 9 const int MAXN = 100000 + 1; 10 11 int n, a[MAXN]; 12 priority_queue<int> q1; 13 priority_queue<int, vector<int>, greater<int> > q2; 14 15 int main() { 16 scanf("%d", &n); 17 for(int i = 1; i <= n; i++) scanf("%d
", &a[i]); 18 q1.push(a[1]); 19 printf("%d\n", a[1]); 20 for(int i = 2; i <= n; i++) { 21 if(a[i] > q1.top()) q2.push(a[i]); 22 else q1.push(a[i]); 23 while(abs(q1.size() - q2.size()) > 1) { 24 if(q1.size() > q2.size()) q2.push(q1.top()), q1.pop(); 25 else q1.push(q2.top()), q2.pop(); 26 } 27 if(i & 1) { 28 if(q1.size() > q2.size()) printf("%d\n", q1.top()); 29 else printf("%d\n", q2.top()); 30 } 31 } 32 }

【洛谷】【堆】P1168 中位數