首页 > 其他分享 >「笔记」对顶堆动态维护中位数

「笔记」对顶堆动态维护中位数

时间:2024-04-26 10:59:11浏览次数:21  
标签:greater less 中位数 笔记 插入 动态 operatorname size

目录

写在前面

妈的为啥我不会这个

问题

给定 \(n\) 次操作,要求动态地维护一个可重集合,每次操作为下列三种形式之一:

  • 给定参数 \(x\),向集合中插入一个权值 \(x\)。
  • 给定参数 \(x\),删除集合中已存在的一个权值 \(x\)。
  • 查询集合的中位数。

要求在 \(O(n\log n)\) 时间复杂度内实现。

思路

考虑对当前可重集合维护两个 multiset,记它们分别为 \(A\) 与 \(B\),\(A\) 中存小于等于中位数的权值,\(B\) 中存大于等于中位数的权值,且钦定 \(\operatorname{size}(A) \ge \operatorname{size}(B), \left|\operatorname{size}(A) - \operatorname{size}(B)\right|\le 1\)。则在此限制下 \(A\) 中最大的数即为集合的中位数。

考虑在上述限制下如何维护 \(A, B\):

  • 为了方便首先在 \(A\) 中插入极小值,\(B\) 中插入极大值。
  • 对于插入操作,若给定参数 \(x\le \operatorname{max}\{A\}\),则将 \(x\) 插入 \(A\),否则插入 \(B\)。
  • 对于删除操作,先查询 \(A\) 中是否存在 \(x\),若存在则直接删除,否则在 \(B\) 中查询并删除。
  • 每次插入删除操作后,都进行调整操作:若 \(\operatorname{size}(A) > \operatorname{size}(B) + 1\) 则不断取出 \(A\) 中最大值插入 \(B\);若 \(\operatorname{size}(B) > \operatorname{size}(A)\) 则不断取出 \(B\) 中最小值插入 \(A\)。
  • 完成调整后,查询 \(A\) 中最大的数即为整个集合的中位数。

发现在上述过程中,单次调整至多仅会调整一个元素,则仅有常数次对 set 的操作。则单次插入/删除时间复杂度 \(O(\log n)\) 级别,查询 \(O(1)\) 级别。

注意 multiset.erase 时,若传入的为值则会将所有值均删除;传入迭代器才仅会删除一个。

代码

namespace Set {
  const int kInf = 1e9 + 2077;
  std::multiset<int> less, greater;
  void init() {
    less.clear(), greater.clear();
    less.insert(-kInf), greater.insert(kInf);
  }
  void adjust() {
    while (less.size() > greater.size() + 1) {
      std::multiset<int>::iterator it = (--less.end());
      greater.insert(*it);
      less.erase(it);
    }
    while (greater.size() > less.size()) {
      std::multiset<int>::iterator it = greater.begin();
      less.insert(*it);
      greater.erase(it);
    }
  }
  void add(int val_) {
    if (val_ <= *greater.begin()) less.insert(val_);
    else greater.insert(val_);
    adjust();
  }
  void del(int val_) {
    std::multiset<int>::iterator it = less.lower_bound(val_);
    if (it != less.end()) {
      less.erase(it);
    } else {
      it = greater.lower_bound(val_);
      greater.erase(it);
    }
    adjust();
  }
  int get_middle() {
    return *less.rbegin();
  }
}

例题

The 2023 ICPC Asia Jinan Regional Contest - K

写在最后

妈的为啥我不会这个

标签:greater,less,中位数,笔记,插入,动态,operatorname,size
From: https://www.cnblogs.com/luckyblock/p/18159496

相关文章

  • VUE Element Plus-table动态添加删除行
     <template><divclass="app-container"><el-rowstyle="margin-top:20px"><el-col:span="24"style="border-left:5pxsolid#1d6ced;margin-bottom:10px"><labelstyle=......
  • MyBatis 动态 SQL 最全教程,这样写 SQL 太优雅了!
    一、MyBatis动态sql是什么动态SQL是MyBatis的强大特性之一。在JDBC或其它类似的框架中,开发人员通常需要手动拼接SQL语句。根据不同的条件拼接SQL语句是一件极其痛苦的工作。例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态SQL恰好解......
  • [笔记]html+css基础知识
    1.html标签单标签<br/>:换行用<meta/>:存字符编码,作者,版权,关键字,网页说明等信息,不显示在浏览器中a.比如:<metahttp-equiv="Content-Type"content="text/html;charset=gb2312"/><hr/>:插入一条水平线,两个标签表示插入两条<img/>:插入图片a.src是图像存储url或名......
  • 论文笔记-Non-intrusive classification of gas-liquid flow regimes in an S-shaped
    目标:使用深度神经网络对S形立管中的流态进行分类该分类器与四种传统的机器学习分类器进行了比较:即AdaBoost分类器、bagging分类器、额外树分类器和决策树分类器小波分析在流态分类中的应用可以有效地提取多相流行为的特征。使用信号处理方法进行流态分类,包括峰值点计数、......
  • 吉司机线段树 学习笔记
    前言第一篇笔记咋是这个啊?(吉司机,指Qerrj(急急司机(?))所以人是会怀念过去的,我称Qerrj急急(只是不是吉吉)很大原因也是初中的吉吉,初中又是因为小学有吉吉。不过现在一般叫(初中的)吉吉邱元教授就是了(?)他还在林荫呢,什么时候见见他啊。吉司机线段树基础基于最基本的区间加线段树,但......
  • 笔记:拓扑排序
    定义拓扑排序(Topologicalsorting),是对一个DAG排序的算法。对于排序后的序列\(s\),设\(t_i\)是节点\(i\)在\(s\)中的位置,那么该DAG上的每条边\(u\tov\),\(t_u<t_v\)。换句话说,就是每条边\(u\tov\),\(u\)不能在\(v\)的后面。模板link。考虑两种算法,分别基于广......
  • 学习笔记447—本地部署 Llama3 – 8B/70B 大模型!最简单的方法: 支持CPU /GPU运行 【3种
    本地部署Llama3–8B/70B大模型!最简单的方法:支持CPU/GPU运行【3种方案】目前在开源大模型领域,Llama3无疑是最强的!这次Meta不仅免费公布了8B和70B两个性能强悍的大模型,400B也即将发布,这是可以和GPT-4对打的存在!今天我们就来介绍3各本地部署方法,简单易懂,非常适合新手!1.G......
  • 论文笔记-Machine learning based flow regime recognition in helically coiled tube
    对象:进行了螺旋线圈中的自动两相流模式识别方法:X射线照相的空隙率测量数据+聚类+KNN、RF、SVM目标:模式识别关注特征:结果:聚类分类:模型是随机森林(RF)分类器、KNN分类器和SVM(参见第1节)。为了优化超参数并估计分类器精度,所有模型均采用嵌套5×5交叉验证方案,如图1所示。......
  • 帆软笔记
    一:表格值自定义显示1、日期型格式化:=FORMAT($$$,"MM月dd日"),或者  2、普通值自定义显示:if($$$='SW_1','丝网一号机',if($$$='SW_2','丝网二号机','丝网三号机')),或者 二:从数据集中再次筛选,如Sum运算SUM(表格.select(QTY_SW,SHIFT_CODE_NAME=B3&&W......
  • 洛谷题单指南-动态规划2-P2758 编辑距离
    原题链接:https://www.luogu.com.cn/problem/P2758题意解读:对a字符串最少操作几次可以变成b字符串,看似无从下手,可以从内部递推关系着手。解题思路:设dp[i][j]表示将a字符串1~i变成b字符串1~j的最少操作次数,字符串下标从1开始。如何思考递推?可以从最后一步为切入点!最后一步对a[i]......