【每日一题】Running Median

Running Median

http://www.nowcoder.com/questionTerminal/61923e5d90b6440a918b47aed96c4efb

题意:动态地输入输出,如果输入的数个数为奇数就输出当前的中位数

对顶堆的经典题,附上大佬的关于对顶堆的博客一篇:
https://www.cnblogs.com/SGCollin/p/9673252.html

这题需要动态地维护中位数,用一个大根堆和小根堆;
构造对顶堆应满足以下性质:
1.上面的堆是小根堆,下面的堆是大根堆;
2.上面的堆内的所有元素都不小于下面的堆的对顶元素;
3.下面的堆的元素个数最多只比上面的个数多1个;
然后对于一个新读入的元素x,如果 x 不大于下面的大根堆的对顶元素,就把x放到下面的大根堆,否则放到上面的小根堆,这样可以维护上述的第二条性质;
但是这样不一定也能满足第三条性质,还需要调整:检查两个堆的元素个数是否满足第三条性质,若不满足分为两种情况:
①下面的大根堆元素个数太少了,就把上面的小根堆的堆顶元素给大根堆;
②下面的大根堆元素太多了,就把大根堆的堆顶给小根堆;

#include <cstdio>
#include <queue>
using namespace std;
priority_queue<int> down;//大根堆
priority_queue<int,vector<int>,greater<int> > up;//小根堆 
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int id,n;scanf("%d%d",&id,&n);
        while(down.size()) down.pop();
        while(up.size()) up.pop();
        printf("%d %d\n",id,(n+1)>>1);
        int idx = 0;//这个样例已经输出的个数 
        for(int i = 1;i <= n;i++){
            int x;scanf("%d",&x);
            //维护第二条性质 
            if(down.empty()||x <= down.top()) down.push(x);
            else up.push(x);
            //维护第三条性质
            if(down.size() > up.size()+1) up.push(down.top()),down.pop();
            if(up.size() > down.size()) down.push(up.top()),up.pop();
            if(i&1){
                printf("%d ",down.top());
                if(++idx%10 == 0) puts("");
            } 
        }
        if(idx%10) puts("");        
    }
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务