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

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

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

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();}
};

结构介绍

解释一下两个堆 \(q1\) 和 \(q2\) :

q1

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

q2

\(q2\) 存储了 \(q1\) 中已删除的元素

操作介绍

push

我们看到 push 操作,很平常,就是向 \(q1\) 中 \(push\) 一个新的元素

erase

这就是这个黑科技的精华了,我们向 \(q2\) 中 \(push\) 一个元素表示在 \(q1\) 中它已经被删除了

pop

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

此时我们把两个堆一起 \(pop\) 就好了,直到堆顶元素不同或者 \(q2\) 没元素了

top

这里就是先进行和 \(pop\) 中类似的操作,删除已经 \(erase\) 的元素,然后取出堆顶

top2

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

size

这个就是返回堆大小的,可以知道堆当前真实大小就是 \(q1\) 大小减去 \(q2\) 大小

总结

新技能 \(get\) !

但是注意一下,这里我们的 \(erase\) 操作必须合法, 否则会出现 \(bug\)

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

原文地址:https://www.cnblogs.com/Judge/p/10557516.html

时间: 2024-10-16 02:16:39

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

UVa 11987 Almost Union-Find(支持删除操作的并查集)

传送门 Description I hope you know the beautiful Union-Find structure. In this problem, you’re to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations: 1 p q

SQL语句的添加、删除、修改多种方法 —— 基本操作

添加.删除.修改使用db.Execute(Sql)命令执行操作 ╔----------------╗ ☆ 数据记录筛选 ☆ ╚----------------╝ 注意:单双引号的用法可能有误(没有测试) Sql = "Select Distinct 字段名 From 数据表" Distinct函数,查询数据库存表内不重复的记录 Sql = "Select Count(*) From 数据表 where 字段名1>#18:0:0# and 字段名1< #19:00#

bzoj1503 Splay 维护名次数,支持删除

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1503 题解: 维护一颗Splay和一个外部变量,树中每个节点表示一个人,节点权值a + 外部变量delta = 该员工工资. 细节看代码. 注意:一进来工资就低于最低工资的人不能算是“离开公司”的人. 1 #include <cstdio> 2 #define fprintf(...) 3 #define maxn 100100 4 5 struct Splay { 6 int key[m

bzoj 2300 动态维护上凸壳(不支持删除)

新技能GET. 用set保存点,然后只需要找前趋和后继就可以动态维护了. 1 /************************************************************** 2 Problem: 2300 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:556 ms 7 Memory:4824 kb 8 ************************************************

优先队列及其基本操作的堆实现

用代码说话 /* 本代码实现优先队列:分为最大优秀队列和最小优先队列 优先队列用于维护一组元素构成的集合S的数据结构,其中的 每一个元素都有一个相关的值,称为关键字. 一个最大优先队列支持以下操作: insert(S,x)向S中插入元素x; maximum(S)返回S中的最大键值元素; extract-max(S)去掉并且返回S中的最大键值元素; increase-key(S,x,k)将元素x的关键字增加到k,假设k要不小于x的原关键字 一个最小优先队列支持以下操作: insert(S,x)向S

干货驾到:Redis5.0支持的新功能说明

Redis5.0支持的新特性说明 文章来自华为云帮助中心华为云DCS的Redis5.x版本继承了4.x版本的所有功能增强以及新的命令,同时还兼容开源Redis5.x版本的新增特性. Stream数据结构 Stream是Redis 5.0引入的一种新数据类型,它是一个全新的支持多播的可持久化消息队列. 点击下方链接,可以了解更多详情. https://www.huaweicloud.com/product/dcs.html Redis Stream的结构示意图如图7-1所示,它是一个可持久化的数据

查找与排序小结

//顺序查找 //主要是为了说明引入"哨兵"的作用 typedef struct { //查找表的数据结构 ElemType *elem; //元素存储空间基址,建表时按实际长度分配,0号单元留空 int TableLen; //表的长度 }SSTable; int Search_Seq(SStable ST,ElemType key){ //顺序表ST中顺序查找键字为key的元素.若找到则返回该元素在表中的位置 ST.elem[0]=key; //"哨兵" for

【数据结构】7. 排序

目录 7.1 排序的基本概念 7.1.1 排序的定义 7.2 插入排序 7.2.1 直接插入排序 7.2.2 折半插入排序 7.2.3 希尔排序 7.3 交换排序 7.3.1 冒泡排序 7.3.2 快速排序 7.4 选择排序 7.4.1 简单选择排序 7.4.2 堆排序 7.5 归并排序和基数排序 7.5.1 归并排序 7.5.2 基数排序 7.6 各种内部排序算法的比较及应用 7.6.1 内部排序算法的比较 7.6.2 内部排序算法的应用 7.7 外部排序 7.7.1 外部排序的基本概念 7.

数据库删除数据不支持表别名

在mysql5.0版本里,不支持删除别名 例如: select * from test where id='3'; 这样是行的 但是: select * from test T1 where T1.id='3'; 这样是不行的!会报1064错误 要是一定要表名字:可以直接这样: select * from test where test.id='3'; 经过测试:在oracle,db2数据库,都是可以在删除语句中使用别名的