1. 程式人生 > >P1168 中位數 - 堆

P1168 中位數 - 堆

對頂堆,維護第k大
考慮維護一個大根堆,一個小根堆。
這兩個堆總大小為當前區間長度,我們維護兩個性質:

1.小根堆總比大根堆多一個元素
2.小根堆所有元素都大於大根堆元素

這樣小根堆的堆頂就是區間中位數。

當需要加入一個新元素時,如果這個元素比小根堆堆頂要大,就加入小根堆中,反之則加入大根堆,這樣可以維護性質2

加入元素後,檢查兩個堆的大小關係,如果大小關係不滿足性質1,就在兩個堆之間搬運元素,由於加入規則的限制我們這樣搬來搬去仍然是符合性質2的

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
priority_queue <int, vector<int>, greater<int> > qmin;
priority_queue <int> qmax;
int n,a[100010];
int main() {
    cin >> n;
    for(int i=1; i<=n ;i++) {
        cin >> a[i];
        if(qmin.empty()) {
            qmin.push(a[i]);
            cout << a[i] << endl;
            continue;
        }
        if(a[i] > qmin.top()) 
            qmin.push(a[i]);
        else 
            qmax.push(a[i]);
        while(qmax.size() > qmin.size()-1) {
            qmin.push(qmax.top());
            qmax.pop();
        }
        while(qmin.size() - 1 > qmax.size()) {
            qmax.push(qmin.top());
            qmin.pop();
        }
        if(i % 2)
            cout << qmin.top() << endl;
    }
    return 0;
}