题目大意:给你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; }