区间第k小数 (可持久化线段树、主席树)

 题意:多次询问,每次询问某区间的第k小数。

可持久化线段树:

掺杂了一点前缀和的思想,对于每一个1 ~ i 的区间都建一个树,每个节点存的都是一个线段树,值存的是当前区间中初始数组按大小排序后[l, r]之间的数的个数,这个l,r指的是每个节点的左右端点。如果想求[l, r]区间内的第k小数,只需要同时遍历[1,l - 1] 以及 [1, r] 两个版本的线段树,因为即使版本不同,线段树的结构是不变的,所以可以发现,如果某个节点区间在老版本里面已经出现了x个数,那么在新版本中的当前区间需要减去x这样才是我们所求的区间里面数的数量,通过查找第k个数的位置找到第k小的数是哪个。

有点乱,直接看代码吧。

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int, string> pis;
const int mod = 1e9 + 7;
const int N = 2e6+ 10;
int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
int n, m, idx;
int o[N], root[N];
struct node{int l, r;int cnt;
}tr[N];
vector<int> nums;int find(int x){//找到对应的离散值return lower_bound(nums.begin(), nums.end(), x) - nums.begin();
}int build(int l, int r){// 建树int p = ++ idx;// 给当前节点分配序号if(l == r) return p;// 区间不可再分,直接返回当前节点序号即可int mid = l + r >> 1; // 找到区间的中点tr[p].l = build(l, mid), tr[p].r = build(mid + 1, r);// 分别对左右儿子进行建树return p;// 将当前树的序号返回
}int insert(int p, int l, int r, int x){// 插入某个元素,p为上一个版本的当前区间的树序号int q = ++ idx;// 为当前子树分配序号tr[q] = tr[p];  // 继承老版本中当前子树的信息if(l == r) {// 需要修改的就是当前位置,将cnt加一即可tr[q].cnt ++;return q;}int mid = l + r >> 1;if(x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);// 需要插入得位置在左儿子else tr[q].r = insert(tr[p].r, mid + 1, r, x);// 在右儿子tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt; // 更新当前版本的当前区间的cnt状态return q;//返回当前的序号
}int query(int q, int p, int l, int r, int k){// 查询l,r区间的第k小数,q为当前版本,p为老版本if(l == r) return r; // 找到所查元素int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;// 通过新老版本的差可以得出当前区间的真实数量int mid = l + r >> 1;if(k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k);// 再左儿子查左儿子,更新新老版本的左儿子树的序号else return query(tr[q].r, tr[p].r, mid + 1, r, k - cnt);// 更新右儿子树的序号,以及新的k的状态
}inline void sovle() {cin >> n >> m;for(int i = 1; i <= n; i ++){cin >> o[i];nums.push_back(o[i]);}sort(nums.begin(), nums.end());nums.erase(unique(nums.begin(), nums.end()), nums.end());//以上都是在进行离散化操作root[0] = build(0, nums.size() - 1);// 建立一个空的线段树,用于下一次操作继承,哨兵作用for(int i = 1; i <= n; i ++) // 没差一次就建立一个新版本的树root[i] = insert(root[i - 1], 0, nums.size() - 1, find(o[i]));while(m --){int l, r, k;cin >> l >> r >> k;int i = query(root[r], root[l - 1], 0, nums.size() - 1, k);//查询操作cout << nums[i] << endl;	}
}signed main(void) {IOS;int t = 1;
//	cin >> t;while(t --) sovle();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162072.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AGC】鸿蒙应用软件包上传问题解析

【问题背景】 近期收到了一些反馈&#xff0c;一些鸿蒙元服务开发者在发布应用市场的过程中&#xff0c;上传.app包时遇到了不同的报错&#xff0c;导致上传失败&#xff0c;下面来看一下这些报错的具体原因&#xff0c;如何正确打包上传。 【问题描述1】 HarmonyOS元服务软件…

51单片机PWM控制LED灯渐明渐暗实验

51单片机PWM控制LED灯渐明渐暗实验 1.概述 这篇文章介绍单片机的PWM通过占空比控制LED灯的渐明渐暗效果&#xff0c;通过该实验掌握PWM的原理以及应用它做一些事情。 2.操作步骤 2.1.硬件电路 1.硬件准备 名称型号数量单片机STC12C20521LED彩灯无2晶振12MHZ1电容30pf2电阻…

ubuntu上查看各个进程的实时CPUMEM占用的办法

top常见参数top界面分析system monitorhtop1、查看htop的使用说明2、显示树状结构3、htop使用好文推荐top top的用法应该是最为普遍的 常见参数 -d 更新频率,top显示的界面几秒钟更新一次 -n 更新的次数,top显示的界面更新多少次之后就自动结束了 当然也可以将top日志通过…

Android进阶知识:ANR的定位与解决

1、前言 ANR对于Android开发者来说一定不会陌生&#xff0c;从刚开始学习Android时的一不注意就ANR&#xff0c;到后来知道主线程不能进行耗时操作注意到这点后&#xff0c;程序出现ANR的情况就大大减少了&#xff0c;甚至于消失了。那么真的是只要在主线程做耗时操作就会产生…

RabbitMQ 的网页界面操作说明

启动 上面给用户添加了角色和权限&#xff0c; 我们就可以登录了 先手动创建两个队列&#xff0c;然后再把这两个队列和交换机绑定&#xff0c;就可以发布消息 回到队列中看看有什么变化 队列中显示绑定了交换机 再看一下队列中发生的变化 可以看到队列中收到了信息

基于C#实现树状数组

有一种数据结构是神奇的&#xff0c;神秘的&#xff0c;它展现了位运算与数组结合的神奇魅力&#xff0c;太牛逼的&#xff0c;它就是树状数组&#xff0c;这种数据结构不是神人是发现不了的。 一、概序 假如我现在有个需求&#xff0c;就是要频繁的求数组的前 n 项和&#x…

Redis事务的理解与使用

文章目录 Redis 事务1)基本认识2)事务操作1.MULTI2.EXEC3.错误处理4.DISCARD5.WATCH6.SCRIPT Redis 事务 官方文档&#xff0c;永远是你学习的第一手资料&#xff1a;Redis 事务 1)基本认识 谈到事务&#xff0c;大家首先都会联想到 mysql 中复杂但又功能强大的“事务”&…

SpringBoot——感谢尚硅谷官方文档

SpringBoot——感谢尚硅谷官方文档 1 Spring与SpringBoot1、Spring能做什么1.1、Spring的能力1.2、Spring的生态1.3、Spring5重大升级1.3.1、响应式编程1.3.2、内部源码设计 2、为什么用SpringBoot2.1、SpringBoot优点2.2、SpringBoot缺点 3、时代背景3.1、微服务3.2、分布式分…

Dubbo从入门到上天系列第十八篇:Dubbo引入Zookeeper等注册中心简介以及DubboAdmin简要介绍,为后续详解Dubbo各种注册中心做铺垫!

文章目录 一&#xff1a;Dubbo注册中心引言 1&#xff1a;什么是Dubbo的注册中心&#xff1f; 2&#xff1a;注册中心关系图解 3&#xff1a;引入注册中心服务执行流程 4&#xff1a;Dubbo注册中心好处 5&#xff1a;注册中心核心作用 二&#xff1a;注册中心实现方案 …

10.docker的网络network-概述

1.docker的网络模式 docker共有四种网路模式&#xff0c;分别是bridge、host、none和container. 1.1 bridge bridge,也称为虚拟网桥。在bridge模式下&#xff0c;为每个容器分配、配置IP等&#xff0c;并将容器连接到一个docker0。使用–network bridge命令指定&#xff0c;…

C# Winform使用log4net记录日志

写在前面 Log4Net是从Java的log4j移植过来的&#xff0c;功能也与log4j类似&#xff0c;可以把日志信息输出到文件、数据库、控制台、Windows 事件日志、远程系统日志服务等不同的介质或目标。 Log4Net配置选项丰富灵活&#xff0c;并且可在运行时动态更新配置并应用&#xf…

解析紫光展锐T820 5G芯片——让照片接近原色

紫光展锐系统级安全的高性能5G SoC芯片平台T820&#xff0c;采用八核CPU架构&#xff0c;6nm EUV先进工艺&#xff0c;金融级全内置安全方案&#xff0c;在性能、功耗与5G通信体验等方面&#xff0c;较上一代产品更为出色。 此前&#xff0c;已经为大家讲解过T820的拍照、安全性…

mac跑分工具 Geekbench v6.2.2

Geekbench 6 是一款跨平台的系统性能测试软件&#xff0c;可以对处理器和内存等硬件进行评测&#xff0c;并提供了单核和多核两种测试模式。该软件适用于 Windows、macOS、Linux 和 iOS 等多种操作系统平台。 Geekbench 6 测试可以帮助用户快速准确地了解自己设备的性能表现&am…

PHP中间件实现

目录 1、简单中间实现 2、使用闭包函数实现中间件 在PHP中&#xff0c;中间件是一种常用的设计模式&#xff0c;用于处理请求和响应&#xff0c;它可以在请求到达目标处理程序之前或响应发送给客户端之前执行一些特定的逻辑。中间件提供了一种灵活的方式来修改或扩展应用程序的…

查看当前laravel版本三种方法(笔记二)

1、在终端中使用 Artisan 命令&#xff1a;在 Laravel 项目的根目录下&#xff0c;打开终端&#xff08;命令行界面&#xff09;&#xff0c;然后运行以下命令&#xff1a; php artisan --version 2、控制器中打印版本 var_dump(app()->version()); 3、在 Laravel 项目的根目…

【kubernetes】k8s架构之节点

文章目录 1、集群架构示意图2、概述3、管理3.1 节点名称唯一性3.2 节点自注册3.3 手动节点管理 4、节点状态4.1 地址&#xff08;Addresses&#xff09;4.2 状况&#xff08;Condition&#xff09;4.3 容量&#xff08;Capacity&#xff09;与可分配&#xff08;Allocatable&am…

PTA-输出三角形面积和周长

本题要求编写程序&#xff0c;根据输入的三角形的三条边a、b、c&#xff0c;计算并输出面积和周长。注意&#xff1a;在一个三角形中&#xff0c; 任意两边之和大于第三边。三角形面积计算公式&#xff1a;areas(s−a)(s−b)(s−c)​&#xff0c;其中s(abc)/2。 输入格式&…

某60区块链安全之Call函数簇滥用实战二学习记录

区块链安全 文章目录 区块链安全Call函数簇滥用实战二实验目的实验环境实验原理实验内容实验步骤EXP利用 Call函数簇滥用实战二 实验目的 学会使用python3的web3模块 学会并区分以太坊call、staticcall、delegatecall三种函数调用的特点 找到合约漏洞进行分析并形成利用 实验…

03梯度下降

目录 lambda基础知识 代码 核心算法&#xff1a; lambda基础知识 lambda 是 Python 中的一个关键字&#xff0c;用于创建匿名函数。匿名函数是一种没有具体名称的小型、临时的函数&#xff0c;通常用于一次性的、简单的操作。lambda 函数的语法如下&#xff1a;python Copy c…

计算3个点的6种分布在平面上的占比

假设平面的尺寸是6*6&#xff0c;用11的方式构造2&#xff0c;在用21的方式构造3 2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在平面上有一个点x&#xff0c;11的操作吧平面分成了3部分2a1&#xff0c;2a…