poj 3784 Running Median 二叉堆

传送门


题目大意:
依次添加 n 个数,要求第奇数次添加时,输出当前数列中的中位数。


分析:
维护一个大根堆一个小根堆,大的数插入小根堆,小的数插入大根堆,每次取大根堆堆顶就是中位数


代码如下:(第一次手写二叉堆,所以是抄的POPOQQQ的模板>o< >_<)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=5000+5;
int p,a,m;
struct small_root_heap{//小根堆 
    int heap[maxn],size;
    void insert(int x){
        heap[++size]=x;
        int t=size;
        while(t>1&&heap[t]<heap[t>>1])//不断向上调整直到比父结点不优为止
            swap(heap[t],heap[t>>1]),t>>=1;
    }
    void pop(){//弹顶 
        int t=2;
        heap[1]=heap[size],heap[size--]=0;
        while(t<=size){
            if(heap[t]>heap[t+1]&&t<size)
                t++;
            if(heap[t]<heap[t>>1])//不断向上调整直到比父结点不优为止
                swap(heap[t],heap[t>>1]),t<<=1;
            else
                break;
        }
    }
}topheap,bottomheap,empty;//topheap是小根堆,bottomheap是大根堆
void add(int x){
    if(x<=-bottomheap.heap[1])
        bottomheap.insert(-x);
    else
        topheap.insert(x);//小的插入大根堆,大的插入小根堆 
    //插入,保证下堆的任意元素都小于等于上堆的任意元素   
    //注意一定要和下堆堆顶比较,因为第一次插入后元素一定在下堆,如果和上堆堆顶比较就会WA 
    while(topheap.size>bottomheap.size)
        bottomheap.insert(-topheap.heap[1]),topheap.pop();
    while(bottomheap.size>topheap.size+1)
        topheap.insert(-bottomheap.heap[1]),bottomheap.pop();
    //维护上下堆平衡,保证两堆元素数相等或下堆元素数比上堆元素数多1 
} 
signed main(void){
    scanf("%d",&p);
    while(p--){
        scanf("%d%d",&a,&m);
        topheap=bottomheap=empty;
        printf("%d %d\n",a,(m+1)>>1);
        for(int i=1,x;i<=m;i++){
            scanf("%d",&x);
            add(x);
            if(i&1){
                printf("%d%c",-bottomheap.heap[1],i==m?'\n':' ');
                if(i%20==19)
                    printf("\n");
            } 
        }
    }
    return 0;
}

by >o< neighthorn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值