Running Median---优先队列or主席树
Running Median
https://ac.nowcoder.com/acm/problem/50940
题目链接:https://ac.nowcoder.com/acm/problem/50940
题解:
方法1:对于动态维护中位数,可以选择使用两个优先队列,一个大优先一个小优先,并且保证大小两个优先队列的size相差不超过1即可,中位数一定会在size较大的那个队列的top位置。实时更新中位数,比大于等于中位数的数丢进小优先队列,否则丢进大优先队列,然后维护两个队列的size不超过1即可,比较简单。
方法2:主席树静态查询第k大模板题,建树之后,对于每个符合的奇数段[1,x],x是奇数,查询区间[1,x]的第(x+1)/2大元素即可
由于方法2的代码是模板题,就不提供了方法2代码了。
下面是提供的是方法1代码:
#include <cctype> #include <cfloat> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <algorithm> #include <deque> #include <fstream> #include <functional> #include <iomanip> #include <iostream> #include <istream> #include <iterator> #include <list> #include <map> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <utility> #include <vector> #define PI 3.1415926535898 using namespace std; int main() { int t; cin>>t; while(t--) { int idx,n; cin>>idx>>n; cout<<idx<<" "<<(n+1)/2<<endl; priority_queue<int,vector<int>,greater<int>> Min; priority_queue<int> Max; int Mid; vector<int> ans; for (int i=1; i<=n; i++) { int num; cin>>num; if (i==1) Mid=num; if (num>=Mid) Min.push(num); else Max.push(num); if ((int)Min.size()-(int)Max.size()>1) { num=Min.top(); Min.pop(); Max.push(num); } else if ((int)Max.size()-(int)Min.size()>1) { num=Max.top(); Max.pop(); Min.push(num); } if (i%2) { if ((int)Min.size()>(int)Max.size()) Mid=Min.top(); else Mid=Max.top(); ans.push_back(Mid); } } for (int i=0; i<ans.size(); i++) { if (i) { if (i%10) cout<<" "; else cout<<endl; } cout<<ans[i]; } cout<<endl; } return 0; }