K优先队列——对顶堆(大根堆+小根堆)

简介: 题目描述你需要维护一个队列,支持以下两种操作:1.加入一个非负整数x;2.取出当前队列中第k大的数字。保证进行第二种操作时,队列中至少有k个数字。部分数据经过加密,你需要依次处理每个操作才能获得正确的下一个操作。

题目描述


你需要维护一个队列,支持以下两种操作:

1.加入一个非负整数x;

2.取出当前队列中第k大的数字。

保证进行第二种操作时,队列中至少有k个数字。

部分数据经过加密,你需要依次处理每个操作才能获得正确的下一个操作。


输入


第一行包括三个非负整数n,k,p,分别表示操作次数,参数k以及数据是否进行过加密。

接下来n行,每行先给出一个数opt,表示操作类型。若opt=1,接下来还会有一个非负整数x,若p=0,表示往队列中加入x,若p=1,表示往队列中加入x异或上前一次出队操作取出的数字后得到的结果,如果还未进行过出队操作,把前一次取出的数字看作0。若opt=2,表示要求取出并输出当前队列中第k大的数字。


输出


对于每一个出队操作,输出一个正整数表示答案。


样例输入


5 2 1
1 2
1 3
2
1 3
2


样例输出


2
1


提示


对于100%的数据,1 ≤ k ≤ n ≤ 2∗105 ,0 ≤ x ≤ 109。


之前在upc也做过关于对顶堆的题,在 洛谷  还有这道题


对顶堆是由 大根堆 小根堆组成的一种数据结构,经常用来处理在线第 k 大(小),或者是动态中位数的问题

在这里插上一张图

图片来源:https://www.luogu.com.cn/user/119261

微信图片_20220530170007.png

在这一道题目中适合上面放 小根堆 ,下面放大根堆,小根堆里面的元素的顺序是从小到大排序的,大根堆里面的元素是从大到小排列的。小根堆的堆顶为小根堆中最小的元素,大根堆中的元素是大根堆中最大的元素。


利用这一特点,用上面的小根堆储存大的 k 个元素,其余的元素储存小的部分元素,这样一来,这两个堆也有单调性,即小根堆的堆顶(小根堆中最小的元素)大于大根堆的堆顶(大根堆中最大的元素),满足从上到下递减的关系,所以,每次小根堆的堆顶就是第 K 大的元素。


目标就是动态维护小根堆中尽量满足 K 个元素,不足时如果大根堆中还有元素,就将大根堆中的元素放入小根堆(运行错误在这里),意思就是说,如果大根堆中没有元素就没有办法pop()


code:


#include <bits/stdc++.h>
using namespace std;
#define wuyt main
typedef long long ll;
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
    if(c == '-')Nig = -1,c = getchar();
    while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
    return Nig*x;}
#define read read()
const ll inf = 1e15;
const ll INF = 0x3f3f3f3f;
const int maxn = 3e5 + 7;
const int mod = 998244353;
#define pi 3.14159265358979323846
ll res,ans;
ll n,k,p;
priority_queue <ll ,vector<ll> ,greater<ll> > xiaogen;
priority_queue <ll ,vector<ll> ,less<ll> > dagen;
void in_it(ll x){
    if(xiaogen.size()<k) xiaogen.push(x);
    else{
        if(xiaogen.size()&&xiaogen.top()<x){
            dagen.push(xiaogen.top());
            xiaogen.pop();
            xiaogen.push(x);
        }
        else dagen.push(x);
    }
}
int main()
{
    n=read,k=read,p=read;
    ll temp=0;
    while(n--){
        ll opt=read;
        if(opt==1){
            ll x=read;
            if(p==0) in_it(x);
            else in_it(x^temp);
        }
        else{
            temp = xiaogen.top();
            printf("%lld\n",temp);
            xiaogen.pop();
            if(dagen.size()){
                xiaogen.push(dagen.top());
                dagen.pop();
            }
        }
    }
    return 0;
}
/**
5 2 1
1 2
1 3
2
1 3
2
**/

开发者涨薪指南

48位大咖的思考法则、工作方式、逻辑体系

目录
相关文章
|
6天前
|
前端开发 算法 JavaScript
最小堆最大堆了解吗?一文了解堆在前端中的应用
该文章详细解释了堆数据结构(特别是最小堆)的概念与性质,并提供了使用JavaScript实现最小堆的具体代码示例,包括堆的插入、删除等操作方法。
最小堆最大堆了解吗?一文了解堆在前端中的应用
|
5月前
|
存储 Java
优先级队列(堆)
优先级队列(堆)
41 3
|
4月前
|
存储
数据结构学习记录——什么是堆(优先队列、堆的概念、最大堆最小堆、优先队列的完全二叉树表示、堆的特性、堆的抽象数据类型描述)
数据结构学习记录——什么是堆(优先队列、堆的概念、最大堆最小堆、优先队列的完全二叉树表示、堆的特性、堆的抽象数据类型描述)
63 2
|
5月前
|
存储 安全
堆与优先级队列
堆与优先级队列
35 0
|
5月前
|
存储 算法 安全
堆 和 优先级队列(超详细讲解,就怕你学不会)
堆 和 优先级队列(超详细讲解,就怕你学不会)
|
5月前
|
存储
二叉树——堆详解
二叉树——堆详解
33 0
|
12月前
|
存储 算法
优先级队列(堆)&&  堆排序
优先级队列(堆)&&  堆排序
44 0
|
5月前
|
机器学习/深度学习 算法
二叉树-堆应用(2)
二叉树-堆应用(2)
38 1
|
5月前
二叉树-堆应用(1)
二叉树-堆应用(1)
31 0
|
5月前
|
存储 机器学习/深度学习 算法
二叉树与堆
二叉树与堆