首页 > 其他分享 >洛谷题单指南-二叉堆与树状数组-P1801 黑匣子

洛谷题单指南-二叉堆与树状数组-P1801 黑匣子

时间:2024-11-05 15:30:27浏览次数:1  
标签:q1 大根堆 cnt int 洛谷题 元素 二叉 堆堆 P1801

原题链接:https://www.luogu.com.cn/problem/P1801

题意解读:动态维护一组序列,并随时可以求第k小的值,每次求第k小的顺序是递增的,比如第一次取第1小,然后是第2小,以此类推。

解题思路:

对于求第k小的问题,已经介绍过几种方案:

1、快选算法,每次查询时间复杂度logn,传送门:https://www.cnblogs.com/jcwy/p/17992288

2、平衡树,每次查询时间复杂度logn,传送门:https://www.cnblogs.com/jcwy/p/18513114

这里,介绍另一种做法,可以借助于堆实现求第k小问题:

定义两个堆,一个大根堆q1,一个小根堆q2,当前要查询的元素是第cnt+1个

我们可以设定,大根堆存的是前最小的cnt个元素,其余元素存入小根堆,这样一来,每次要查询元素,直接取小根堆堆顶即可

问题关键就在于如何维护两个堆?

关键点1:当要插入一个元素,可以先把元素放入大根堆,如果大根堆数量超过cnt,则将堆顶移至小根堆。

关键点2:当要查询一个元素,直接返回小根堆堆顶,把cnt++。

关键点3:当上一步把cnt++之后,大根堆的元素数量可能不符合要求了,下一次小根堆堆顶就不是第cnt+1个,还需要判断大根堆元素数量是否不足cnt个,如果是则将小根堆堆顶移至大根堆。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 200005;
int n, m, cnt;
int a[N], h[N];
priority_queue<int> q1; //大根堆,存最小的前cnt个数
priority_queue<int, vector<int>, greater<int>> q2; //小根堆,堆顶是第cnt+1小的数

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int u;
    for(int i = 1; i <= m; i++) 
    {
        cin >> u;
        h[u]++;
    }   
    for(int i = 1; i <= n; i++)
    {
        q1.push(a[i]);
        
        if(q1.size() > cnt) //如果大根堆数量超过cnt
        {
            q2.push(q1.top()); //将大根堆堆顶元素移到小根堆
            q1.pop();
        }

        while(h[i]--) //第i个元素插入后有多次get操作
        {
            cout << q2.top() << endl; //取小根堆堆顶即第cnt+1小的数
            cnt++;

            if(q1.size() < cnt) //cnt更新后,如果大根堆元素个数不足cnt
            {
                q1.push(q2.top()); //则将小根堆堆顶元素移到大根堆
                q2.pop();
            }
        }
    }
    return 0;
}

 

标签:q1,大根堆,cnt,int,洛谷题,元素,二叉,堆堆,P1801
From: https://www.cnblogs.com/jcwy/p/18528124

相关文章

  • 洛谷题单指南-二叉堆与树状数组-P3378 【模板】堆
    原题链接:https://www.luogu.com.cn/problem/P3378题意解读:实现二叉堆。解题思路:二叉堆本质上一棵完全二叉树,根节点称为堆顶,根据特性不同分为有两种:大根堆:所有父节点的值大于子节点,根节点最大小根堆:所有父节点的值小于子节点,根节点最小主要作用:动态维护序列,并快速找到最大/最......
  • leetcode107. 二叉树的层序遍历 II
    给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)示例1:输入:root=[3,9,20,null,null,15,7]输出:[[15,7],[9,20],[3]]示例2:输入:root=[1]输出:[[1]]示例3:输入:root=[]输出:[]提示:树......
  • 数据结构 ——— 计算链式二叉树叶子节点的个数以及计算链式二叉树的高度
    目录前言链式二叉树示意图​编辑手搓一个链式二叉树计算链式二叉树的叶子节点个数计算链式二叉树的高度 前言上一章学习了计算链式二叉树的节点个数数据结构———计算链式二叉树节点的个数-CSDN博客接下来学习的是计算链式二叉树叶子节点的个数以及计算链式二叉......
  • 二叉树的一些相关操作
    前言    链式结构二叉树的访问基本使用递归来进行访问,同时也可以体现出递归的暴力美学。因为有涉及到二叉树的相关操作,因此先要手动构造一个二叉树,在对其进行一些操作。        本篇一切对二叉树的操作都基于我创建的二叉树        这个是我构造的......
  • 二叉树的递归遍历(前、中、后序)
    二叉树的递归遍历题目链接:前序遍历:LeetCode144中序遍历:LeetCode94后序遍历:LeetCode145描述给你二叉树的根节点root,返回它节点值的前序、中序、后序遍历。示例1:前序遍历输入:root=[1,null,2,3]输出:[1,2,3]示例2:中序遍历输入:root=[1,null,......
  • 洛谷题单指南-字符串-P6824 「EZEC-4」可乐
    原题链接:https://www.luogu.com.cn/problem/P6824题意解读:已知整数序列a[i],i在1~n,有整数k,求一个整数x,要求a[i]^x<=k,使得符合要求的a[i]数量最多,求这个数量。解题思路:1、确定x的范围由于a[i]^x<=k,因此,x的有效二进制位不可能超过a[i],而a的取值范围<=1000000,因此x差不多......
  • 【笔记/模板】二叉搜索树-平衡树
    二叉搜索树www.luogu.com.cn定义二叉搜索树(\(\text{BinarySearchTree}\))是一种形状如二叉树的数据结构,用于快速查找和增加删除操作,它有如下几个特殊性质:空树是二叉搜索树。若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。若二叉搜索树的右......
  • 数据结构 ——— 链式二叉树的前中后序遍历递归实现
    目录前言链式二叉树示意图​编辑手搓一个链式二叉树链式二叉树的前序遍历链式二叉树的中序遍历链式二叉树的后序遍历 前言在上一章学习了链式二叉树的前中后序遍历的解析数据结构———链式二叉树的前中后序遍历解析-CSDN博客接下来要学习的是代码实现链式二叉树......
  • 【数据结构】二叉树——堆
    一、二叉树的概念与结构二叉树的概念二叉树是树的一种,二叉树的特殊之处在于,每个根节点都可以有两个子节点,可以两个子节点都为空,或者一个为空,一个不为空,或者两个都有数,在构建二叉树的节点时就可以看出:现实中的二叉树:就像这颗树,每次分叉都分出两个枝条,这就是一个二叉树......
  • 二叉树进阶-二叉搜索树
    目录1.二叉树的概念2.二叉搜索树的操作2.1二叉搜索树的结构2.2实现节点的查找(find)2.3实现增加节点(insert)2.4实现删除节点(erase)2.5析构函数2.6二叉搜索树的完整实现3.二叉搜索树的应用3.1K模型3.2KV模型4.二叉搜索树的性能分析1.二叉树的概念二叉搜索树也叫二......