堆:支持删除任意元素以及一些其他基本操作的堆

代码1:转载于https://blog.csdn.net/weixin_45630722/article/details/108286961

struct heap {//手写实现删除任意位置数值的堆
    priority_queue<int> A , B;   //A存储了当前所有元素(包括未删除元素),

                                                 //Bq2q2 存储了 q1q1 中已删除的元素
    void push(int x) {
        A.push(x);
    }
    
    void erase(int x) {
        B.push(x);
    }
    
    void pop() {
        while(B.size() && A.top() == B.top()) A.pop(), B.pop();
        A.pop();
    }
    
    int top() {
        while(B.size() && A.top() == B.top()) A.pop(), B.pop();
        if(!A.size()) return 0;
        return A.top();
    }
    
    int size() {
        return A.size() - B,size();
    }
    
    int stop() {
        if(size() <  2) return 0;
        int x = top(); pop();
        int y = top(); push(x);
        return y;        
    }
} ALL, First[110000], Second[110000];

代码2(转载于https://www.cnblogs.com/Judge/p/10557516.html

支持删除任意元素以及一些其他基本操作的堆

阅读目录(Content)

安利一个黑科技,不知道是谁发明的(好像也有些年代了?)

其实这个黑科技的本质就是一个大根堆,不同的是 它支持删除堆内任意元素,同时也支持堆的基本操作

code

代码如下:

struct Heap{ priority_queue<int> q1,q2;
	inline void push(int x){q1.push(x);}
	inline void erase(int x){q2.push(x);}
	inline void pop(){for(;q2.size()&&q1.top()==q2.top();q1.pop(),q2.pop());if(q1.size())q1.pop();}
	inline int top(){for(;q2.size()&&q1.top()==q2.top();q1.pop(),q2.pop());return q1.top();}
	inline int top2(){int val,ret; val=top(),pop(),ret=top(),push(val); return ret;}
	inline int size(){return q1.size()-q2.size();}
};

结构介绍

解释一下两个堆 q1q1 和 q2q2 :

q1

q1q1 存储了当前所有元素(包括未删除元素)

q2

q2q2 存储了 q1q1 中已删除的元素

操作介绍

push

我们看到 push 操作,很平常,就是向 q1q1 中 pushpush 一个新的元素

erase

这就是这个黑科技的精华了,我们向 q2q2 中 pushpush 一个元素表示在 q1q1 中它已经被删除了

pop

这里就要用到 q2q2 里面的元素了,如果堆顶的元素已经被 eraseerase 过,那么它此时应该在 q2q2 中的堆顶

此时我们把两个堆一起 poppop 就好了,直到堆顶元素不同或者 q2q2 没元素了

top

这里就是先进行和 poppop 中类似的操作,删除已经 eraseerase 的元素,然后取出堆顶

top2

有点骚,这个操作可以取出堆中的次大值,而 top3top3 、top4top4 以此类推(虽说不怎么用到)

size

这个就是返回堆大小的,可以知道堆当前真实大小就是 q1q1 大小减去 q2q2 大小

总结

新技能 getget !

但是注意一下,这里我们的 eraseerase 操作必须合法, 否则会出现 bugbug

或者修改一下操作可能可以支持不合法操作...但我本人觉得不大可能...

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值