zoukankan      html  css  js  c++  java
  • poj 3784 用堆动态求解中位数

    堆真是一种简单而又神奇的数据结构,以前用它求过前kth的数,现在又可以用两个堆来动态求解中位数。

    算法:

      构建一个大顶堆和一个小顶堆,分别记为g和l。

      假设当前中位数为mid,新读入一个数为tmp,则:

      1.如果tmp < mid,则将tmp插入大顶堆,跳到步骤3。

      2.如果tmp >= mid,则将tmp插入小顶堆,跳到步骤4。

      3.如果大顶堆的元素个数比小顶堆多2(两个堆个数不平衡),则将mid插入小顶堆,弹出大顶堆堆顶元素为新的mid。

      4.与步骤3相反,如果小顶堆的元素个数比大顶堆多2,则将mid插入大顶堆,弹出小顶堆堆顶元素为新的mid。

      5.如果两个堆元素个数相同,则mid即为当前序列的中位数;否则,中位数为mid和元素个数较多的堆的堆顶元素的平均值,至此算法描述结束。

    也有人把这个叫做最大最小堆或者是对顶堆的。

    示例代码poj3784:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <queue>
     5 using namespace std;
     6 
     7 priority_queue<int, vector<int>, less<int> > g;
     8 priority_queue<int, vector<int>, greater<int> > l;
     9 const int N = 10000;
    10 int ans[N];
    11 int p;
    12 
    13 int main ()
    14 {
    15     int t;
    16     scanf("%d", &t);
    17     while ( t-- )
    18     {
    19         int _case, n, mid;
    20         scanf("%d%d%d", &_case, &n, &mid);
    21         printf("%d %d
    ", _case, ( n + 1 ) / 2);
    22         p = 0;
    23         ans[p++] = mid;
    24         while ( !l.empty() ) l.pop();
    25         while ( !g.empty() ) g.pop();
    26         for ( int i = 2; i <= n; i++ )
    27         {
    28             int tmp;
    29             scanf("%d", &tmp);
    30             if ( tmp < mid )
    31             {
    32                 g.push(tmp);
    33                 if ( g.size() - l.size() == 2 )
    34                 {
    35                     l.push(mid);
    36                     mid = g.top();
    37                     g.pop();
    38                 }
    39             }
    40             else
    41             {
    42                 l.push(tmp);
    43                 if ( l.size() - g.size() == 2 )
    44                 {
    45                     g.push(mid);
    46                     mid = l.top();
    47                     l.pop();
    48                 }
    49             }
    50             if ( i & 1 )
    51             {
    52                 ans[p++] = mid;
    53             }
    54         }
    55         for ( int i = 0; i < p; i++ )
    56         {
    57             printf("%d", ans[i]);
    58             if ( i % 10 == 9 || i == p - 1 )
    59             {
    60                 putchar('
    ');
    61             }
    62             else
    63             {
    64                 putchar(' ');
    65             }
    66         }
    67     }
    68     return 0;
    69 }

      

  • 相关阅读:
    android学习笔记----启动模式与任务栈(Task)
    二叉搜索树转化成双向链表
    复杂链表的复制
    判断是否为二叉搜索树的后序遍历序列
    树的子结构
    调整数组顺序使奇数位于偶数前面,且奇数之间、偶数之间的相对位置不变
    android学习笔记----HandlerThread学习
    android学习笔记----Handler的使用、内存泄漏、源码分析等一系列问题
    原因分析——cin,coutTLE,scanf,printf就AC
    洛谷P1618_三连击(升级版)
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4645268.html
Copyright © 2011-2022 走看看