标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1670 | Accepted: 823 |
Description
Input
Output
Sample Input
3
1 9
1 2 3 4 5 6 7 8 9
2 9
9 8 7 6 5 4 3 2 1
3 23
23 41 13 22 -3 24 -31 -11 -8 -7
3 5 103 211 -311 -45 -67 -73 -81 -99
-33 24 56
Sample Output
1 5
1 2 3 4 5
2 5
9 8 7 6 5
3 12
23 23 22 22 13 3 5 5 3 -3
-7 -3
Source
对于每个奇数次读入,输出当前已有序列的中位数
维护两个堆,一个大根堆,一个小根堆。大根堆里存较小的数,小根堆里存较大的数。维护好以后,小根堆顶就是中位数。
每次新加入一个数,若该数比中位数大,存入小根堆,否则存入大根堆。
限制小根堆里的数最多比大根堆大1,若不满足,就把小根堆的堆顶弹到大根堆。
以下是代码,基本是抄的233。
结构体里写的是小根堆,为了缩减代码长度,把大根堆取负,也按照小根堆的算法算,就能维护出大根堆。
注意输出格式。mod20==19是为了输出10个中位数就换一行。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=5000; 9 struct pile{ 10 int h[6000]; 11 int cnt; 12 void insert(int x){//插入 13 h[++cnt]=x; 14 int k=cnt; 15 while(k>1 && h[k]<h[k>>1]){//维护 16 swap(h[k],h[k>>1]); 17 k>>=1; 18 } 19 } 20 void pop(){ 21 int k=2; 22 h[1]=h[cnt];//把末尾元素顶上来 23 h[cnt--]=0; 24 while(k<=cnt){ 25 if(h[k]>h[k+1] && k<cnt)k++;//在两个子节点中找较小的 26 if(h[k]<h[k>>1])swap(h[k],h[k>>1]),k<<=1;//把较小的顶上去 27 else break;//满足性质,退出 28 } 29 } 30 }big,small,empty; 31 void ins(int x){ 32 if(x<=-big.h[1]) 33 big.insert(-x); 34 else small.insert(x); 35 while(small.cnt>big.cnt) big.insert(-small.h[1]),small.pop(); 36 while(big.cnt>small.cnt+1) small.insert(-big.h[1]),big.pop(); 37 } 38 int n,m; 39 int main(){ 40 int T; 41 scanf("%d",&T); 42 int i,j; 43 while(T--){ 44 big=small=empty;//初始化 45 scanf("%d%d",&n,&m); 46 int num; 47 printf("%d %d\n",n,(m+1)>>1); 48 for(i=1;i<=m;i++){ 49 scanf("%d",&num); 50 ins(num); 51 if(i&1){//奇数 52 printf("%d",-big.h[1]); 53 if(i==m)printf("\n");else printf(" "); 54 if(i%20==19)printf("\n"); 55 } 56 } 57 } 58 return 0; 59 }
标签:
原文地址:http://www.cnblogs.com/SilverNebula/p/5651805.html