zoukankan      html  css  js  c++  java
  • poj3784 Running Median 题解报告(对顶堆)

    题目传送门

    【题目大意】

    读入一个整数序列,每当已经读入的整数个数为奇数时,输出已经读入的整数构成的序列的中位数。

    【思路分析】

    这题可以使用“对顶堆”的在线做法。为了动态维护中位数,我们可以建立两个二叉堆,一个小根堆、一个大根堆。在以此读入序列的过程中,设当前读入的序列长度为$L$,我们始终保持:

    1.序列中从小到大排名为$1~frac{M}{2}$的整数储存在大根堆中

    2.序列中从小到到排名为$frac{M}{2}+1~M$的整数储存在小根堆中

    任何时候,如果某一个堆中元素过多,打破了这个性质,就取出该堆的堆顶插入另一个堆。这样就能保证序列的中位数为小根堆的堆顶。

    重新读入一个整数$X$时,如果$X$小于当前的中位数,就插入大根堆,否则插入小根堆,在插入后检查并维护上述性质即可,这就是“对顶堆”算法。

    【代码实现】

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #define rg register
     5 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     6 using namespace std;
     7 int T,m,n,mid;
     8 priority_queue<int>q1;//小根堆
     9 priority_queue<int,vector<int>,greater<int> >q2;//大根堆
    10 int main(){
    11     scanf("%d",&T);
    12     while(T--){
    13         scanf("%d%d",&m,&n);printf("%d %d
    ",m,n/2+1);
    14         while(q1.size()>0) q1.pop();
    15         while(q2.size()>0) q2.pop();
    16         go(i,1,n){
    17             int x;scanf("%d",&x);
    18             if(i==1){mid=x;q2.push(x);}
    19             else{
    20                 if(x<mid)q1.push(x);
    21                 else q2.push(x);
    22             }
    23             while((int)q1.size()-(int)q2.size()>1){int y=q1.top();q1.pop();q2.push(y);}
    24             while((int)q2.size()>(int)q1.size()){int y=q2.top();q2.pop();q1.push(y);}
    25             mid=q1.top();
    26             if(i&1) printf("%d ",mid);
    27             if((i&1)&&(i/2+1)%10==0) puts("");
    28         }
    29         if((m/2+1)%10) puts("");
    30     }
    31     return 0;
    32 }
    代码戳这里
  • 相关阅读:
    62-函数的调用
    40-字符串类型内置方法
    47-Python进阶小结
    44-集合的内置方法
    45-数据类型分类
    43-字典类型内置方法
    42-元组类型内置方法
    41-列表类型内置方法
    es6 Reflect对象详解
    微信小程序之公共组件写法
  • 原文地址:https://www.cnblogs.com/THWZF/p/11248741.html
Copyright © 2011-2022 走看看