POJ 3784 Running Median (最大最小堆)
最大最小堆动态求中位数
题意:输入M个数,当已输入的个数为奇数个时输出此时的中位数。
一共有M/2+1个中位数要输出,每一行10个。
分析:
用两个优先队列来模拟最大最小堆。中位数是x,就是有一半数比x小,一半数比x大。
刚好符合堆的特点。
用一个从大到小排序的优先队列q1来模拟小于x的数。
从小到大排序的优先队列q2来模拟大于x的数。
动态维护两个优先队列的元素个数。q1.size()=q2.size() 输入的数为偶数个时,
q1.size()=q2.size()+1 输入的数为奇数个时。
每次要输出的中位数恰好是q1.top().
插入排序也可以诶- -
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #include<set> 11 #include<stack> 12 13 using namespace std; 14 15 typedef long long ll; 16 17 int a[5010]; 18 priority_queue<int> q1; 19 priority_queue<int,vector<int>,greater<int> > q2; 20 21 int main() 22 { 23 int T,cas,m,x; 24 scanf("%d",&T); 25 while(T--) 26 { 27 while(!q1.empty()) q1.pop(); 28 while(!q2.empty()) q2.pop(); 29 int c = 0; 30 memset(a,0,sizeof(a)); 31 scanf("%d%d",&cas,&m); 32 for(int i=1;i<=m;i++) 33 { 34 scanf("%d",&x); 35 if(q1.empty()) 36 q1.push(x); 37 else 38 { 39 if(x>q1.top()) 40 q2.push(x); 41 else q1.push(x); 42 } 43 44 while(q1.size()<q2.size()) 45 { 46 int t = q2.top(); 47 q2.pop(); 48 q1.push(t); 49 } 50 51 while(q2.size()<q1.size()-1) 52 { 53 int t = q1.top(); 54 q1.pop(); 55 q2.push(t); 56 } 57 58 59 if(i&1) 60 { 61 a[c++] = q1.top(); 62 } 63 } 64 printf("%d %d\n",cas,m/2+1); 65 for(int i=0;i<m/2+1;i++) 66 { 67 if(i==0) 68 { 69 printf("%d",a[i]); 70 continue; 71 } 72 if(i%10==0 && i!=0) 73 printf("\n%d",a[i]); 74 else printf(" %d",a[i]); 75 } 76 if((m/2+1)%10) printf("\n"); 77 } 78 return 0; 79 }