[洛谷P1168]中位数
题目大意:给你n个数,问你前1、3、5...个数的中位数是多少。
解题思路:首先,前一个数的中位数一定是第一个数。
之后,每次都会读进两个数。
我们需要做到,如果两个数都小于原来的中位数,那么现在的中位数变成比它小的最大的数。
反之,如果两个数都大于等于原来的中位数,则变成比它大的最小的数。
如果一个小,一个大于等于,则显然中位数不变。
可以想到用一个大根堆保存“比当前中位数小的数”,用一个小根堆保存“大于等于当前中位数的数”,
然后,对于读进来的两个数,把比当前中位数小的放进大根堆里,大于等于当前中位数的放进小根堆里。
如果两个数都小于当前中位数,则把当前中位数放进小根堆里(因为答案变小了),然后当前中位数变为大根堆顶,大根堆顶弹出。
反之则把当前中位数放进大根堆里(因为答案变大了),然后当前中位数变为小根堆顶,小根堆顶弹出。
如果一个大一个小于等于,则中位数不变。
时间复杂度$O(n\log_2 n)$。
C++ Code:
#include<cstdio>
#include<queue>
#include<cctype>
std::priority_queue<int,std::vector<int>,std::greater<int> >small;
std::priority_queue<int>big;
int now,n;
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int main(){
n=readint();
printf("%d\n",now=readint());
for(int i=(n-1)>>1;i;--i){
int a=readint(),p=0;
if(a<now)--p,big.push(a);else ++p,small.push(a);
a=readint();
if(a<now)--p,big.push(a);else ++p,small.push(a);
if(p<0){
small.push(now);
now=big.top();
big.pop();
}else
if(p>0){
big.push(now);
now=small.top();
small.pop();
}
printf("%d\n",now);
}
return 0;
}

浙公网安备 33010602011771号