算法竞赛进阶指南---0x18(对顶堆) Black Box

题面

在这里插入图片描述

题解

在这里插入图片描述

  1. 我们可以用对顶堆来维护一个有序的序列,如图我们只要维护大根堆中的元素是i-1个,那么小根堆的堆顶就是按升序排序后的第i个数,接下俩看两个操作
  1. 对于GET操作,先让i++,然后输出排序后的第i个数,但是题中给定的数组是先输出,后i++(看题),那么我们每次先输出right(小根堆)的堆顶,然后i++,那么left(大根堆)中的元素就应该加+1,我们只需要将小根堆的堆顶放入大根堆中即可维护
  1. 对于ADD操作,如果插入的这个a[i]>=right.top||left.empty(),那么我们直接放入小根堆中即可,因为我们不需要维护小根堆的大小,如果a[i]<right.top,那么我们就要将a[i]放入大根堆中,但是此时大根堆中的元素个数增加了,所以我们还要维护一下大根堆中元素的个数,那么就要将大根堆的堆顶放入小根堆中即可

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>


using namespace std;
const int N = 3e4 + 10;

int n, m;
int a[N], b[N];

int main() {
    
    

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    cin >> m >> n;

    for (int i = 0; i < m; i++) cin >> a[i];
    for (int i = 0; i < n; i++) cin >> b[i];

    sort(b, b + n);

    priority_queue<int> left;
    priority_queue<int, vector<int>, greater<int>> right;

    int i = 0, j = 0;
    while (i < m || j < n) {
    
    
        //GET操作
        while (j < n && b[j] == i) {
    
    
            cout << right.top() << endl;
            left.push(right.top());
            right.pop();
            j++;
        }

        //ADD操作
        if (left.empty() || a[i] >= right.top()) right.push(a[i]);
        else {
    
    
            left.push(a[i]);
            right.push(left.top());
            left.pop();
        }
        i++;

    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/114280081