模板 - 对顶堆

本文介绍了一种使用对顶堆(双堆)数据结构来动态维护序列中第K大值的方法,适用于元素添加场景。通过两个堆分别存储最大值和最小值,实现了高效查找和维护序列中特定位置的数值。

https://www.luogu.org/problemnew/show/P1168
https://www.luogu.org/problemnew/show/P3871

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

struct Double_Heap{
    //对顶堆动态维护一段只能添加的序列,寻找其中的第k大值
    //当然要是删除也是第k大值是可以维护的
    //由于堆排序的特殊性每次调整k的位置不需要对整个序列进行重排,在k变化不是很剧烈的情况很好
    //O(dklogn)dk是k的变化量

    priority_queue<int> mpq;//存放最小的若干个数的大顶堆
    priority_queue<int,vector<int>,greater<int> > Mpq;//存放最大的若干个数的小顶堆

    //需要的元素维持在mpq的堆顶

    void insert(int num){
        if(!Mpq.empty()&&num>Mpq.top()){
            //保证Mpq里放的是最大的若干个数,若新数比Mpq最小的要大,则交换
            Mpq.push(num);
            num=Mpq.top();
            Mpq.pop();
        }
        mpq.push(num);//新数插入小根堆
    }

    int find_kth(int k){
        //寻找第k大数,k从1开始计算,需要保证k在size范围内
        while(mpq.size()>k){
            //mpq现在元素过多,把他们插进Mpq
            Mpq.push(mpq.top());
            mpq.pop();
        }
        while(mpq.size()<k){
            //mpq现在元素过少,把从Mpq插回来
            mpq.push(Mpq.top());
            Mpq.pop();
        }
        return mpq.top();
    }
}dh;

int n,b;
int a[100005];

int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        dh.insert(a[i]);
        if(i&1){
            printf("%d\n",dh.find_kth((i+1)/2));
        }
    }
}

转载于:https://www.cnblogs.com/Yinku/p/11016017.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值