此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。
题目链接:http://poj.org/problem?id=3784
题目大意:
依次给出n个数字,求在数据输入过程中的所有中位数。(共有(n+1)/2个)
输入格式:
输入一个数字P(1<=P<=1000),表示数据组数。
对于每组数据,第一行输入数据组号和数字总个数(1<=个数<=9999),中间以一个空格隔开。
接下来每行给出至多10个数字。
输出格式:
对于每组数据,第一行输出数据组号和中位数个数,中间以一个空格隔开。
接下来每行输出至多10个数字,表示即时中位数。
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
分析:
对顶堆,即用两个堆,一个大根堆一个小根堆。每次比较两个堆的堆顶,如果不相等就交换堆顶,否则堆顶即为所要求的中位数。
证明不再给出,想想应该都明白。
AC代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 7 inline void read(int &x) 8 { 9 char ch = getchar(),c = ch;x = 0; 10 while(ch < ‘0‘ || ch > ‘9‘) c = ch,ch = getchar(); 11 while(ch >= ‘0‘ && ch <= ‘9‘) x = (x<<1)+(x<<3)+ch-‘0‘,ch = getchar(); 12 if(c == ‘-‘) x = -x; 13 } 14 15 std::priority_queue <int> lq,sq; 16 //lq为大根堆,sq为小根堆 17 18 inline void init() 19 { 20 while(!lq.empty()) 21 lq.pop(); 22 while(!sq.empty()) 23 sq.pop(); 24 } 25 26 int main() 27 { 28 // freopen("1.txt","r",stdin); 29 int n,t,x,a,b,cnt; 30 read(t); 31 while(t --) 32 { 33 read(cnt); 34 read(n); 35 init(); 36 printf("%d %d\n",cnt,(n+1)/2); 37 for(int i = 1;i <= n;++ i) 38 { 39 read(x); 40 lq.push(x),sq.push(-x); 41 if(i%2 == 0) continue; 42 while(lq.top() != -sq.top()) 43 { 44 a = lq.top(),lq.pop(); 45 b = -sq.top(),sq.pop(); 46 sq.push(-a),lq.push(b); 47 } 48 printf("%d ",lq.top()); 49 if(((i+1)/2)%10 == 0) puts(""); 50 else if((n%2 == 1 && i == n) || (n%2 == 0 && i == n-1)) puts(""); 51 } 52 } 53 return 0; 54 }
时间: 2024-10-10 10:15:12