洛谷 P1801 黑匣子 对顶堆

洛谷 P1801 黑匣子 对顶堆

题解:

用两个堆来维护,一个小根堆,一个大根堆。
在这里插入图片描述
对顶堆:可以动态维护第k大的值(比如中位数),每次操作logn
如果说上面是个小根堆,下面是个大根堆,小根堆的元素都大于大根堆的元素,那么我们可以发现:每一层节点从上往下逐层递减
(1)我们保证大根堆一直有i-1个元素,这样小根堆的堆顶就是第i大的元素。
(2)我们首先依次向大根堆中添加元素,若达到了i个,就把大根堆的根元素加入小根堆。
(2)因为i在依次递增,所以在get操作中,我们需要把小根堆的堆顶元素重新放入大根堆,以保证大根堆始终有i-1个元素。

代码如下:

#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;

int a[200005];

int main(){
    priority_queue<int> q1;//大根堆
    priority_queue<int,vector<int>,greater<int> >q2;//小根堆
    int n,m,r=1,q;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&q);
        for(int j=r;j<=q;j++){
            q1.push(a[j]);
            if(q1.size()==i){//若大根堆元素已经有i个,则把大根堆堆顶元素移到小根堆
                             //以保证大根堆有i-1个元素,小根堆堆顶即为第i大的元素
                q2.push(q1.top());
                q1.pop();
            }
        }
        r=q+1;
        printf("%d\n",q2.top());
        q1.push(q2.top());
        q2.pop();
    }
    return 0;
}
发布了253 篇原创文章 · 获赞 15 · 访问量 7999

猜你喜欢

转载自blog.csdn.net/weixin_44123362/article/details/103875871