双堆求动态中位数
acwing 106.动态中位数
https://www.acwing.com/problem/content/108/


这题可以用两个堆完成,用一个大根堆存储中位数左边的数,用一个小根堆存储中位数右边的数。
因此,我们需要维护两个堆的一个性质:
两个堆的数字数目需要相同(为了方便,将中位数也算在左边的大根堆中,所以实际上大根堆会比小根堆的数目多一个)。
①每次读入一个数,判断大根堆$down$是否为空,若空, 就插入。或者当前的数$x$是否小于大根堆$down$的堆顶,是就插入,否则就插入小根堆$up$。
②然后判断大根堆$down$的数目是不是比小根堆$up$的数目$+1$还要大,如果还要大,就需要将大根堆$down$的堆顶元素放入小根堆$up$中。
③然后判断小根堆$up$的数目是不是比大根堆$down$的数目大,是就将小根堆$up$的堆顶元素插入大根堆$down$中。
然后在总数目为奇数的时候,大根堆$down$的堆顶元素就是当前序列的中位数。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 9 10 int main(){ 11 int T; 12 cin >> T; 13 while(T --) 14 { 15 int L, m; 16 cin >> L >> m; 17 18 priority_queue<int> down; 19 priority_queue<int, vector<int>, greater<int>> up; 20 int cnt = 0; 21 cout << L << " " << (m + 1) / 2 << endl; 22 23 for(int i = 1 ; i <= m ; i ++) 24 { 25 int x; 26 cin >> x; 27 28 if(down.empty() || x <= down.top())down.push(x); 29 else up.push(x); 30 31 32 if(down.size() > up.size() + 1)up.push(down.top()), down.pop(); 33 if(up.size() > down.size())down.push(up.top()), up.pop(); 34 35 if(i % 2) 36 { 37 cout << down.top() << " "; 38 if( ++ cnt % 10 == 0)cout << endl; 39 } 40 41 } 42 if(cnt % 10)cout << endl; 43 } 44 return 0; 45 }

浙公网安备 33010602011771号