区间第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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生产订单自动下达

文章目录 1 Introduction2 Detail2.1 input MM02 3 Summary 1 Introduction Production order is released order by automation . We can set the material for it . The method is the detial . 2 Detail 2.1 input MM02 please choose work Scheduling please choose S…

算法分析-三壶谜题

一.题目需求 有一个充满水的8品脱的水壶和两个空水壶&#xff08;容积分别是5品脱和3品脱&#xff09;。 通过将水壶完全倒满水和将水壶的水完全倒空这两种方式&#xff0c;在其中的一个水壶中得到4品脱的水。 二、算法思想 1.算法分析 1.1. 采用的算法思想是将某个时刻水壶…

9.3 Windows驱动开发:内核解析PE结构节表

在笔者上一篇文章《内核解析PE结构导出表》介绍了如何解析内存导出表结构&#xff0c;本章将继续延申实现解析PE结构的PE头&#xff0c;PE节表等数据&#xff0c;总体而言内核中解析PE结构与应用层没什么不同&#xff0c;在上一篇文章中LyShark封装实现了KernelMapFile()内存映…

priority_queue简单实现(优先级队列)(c++)

priority_queue priority_queue介绍逻辑实现框架调整算法adjust_up()adjust_down() 仿函数/比较函数仿函数特性 构造函数迭代器区间构造 完整优先级队列代码 priority_queue介绍 pri_que是一个容器适配器&#xff0c;它的底层是其他容器&#xff0c;并由这些容器再封装而来。类…

Win10之bandicam录音无声音问题(七十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

分布式进阶-链路追踪SpringCloudSleuth、Zipkin【实战篇】

一、前言 我们在使用微服务的时候&#xff0c;往往设计到各个微服务之间的调用&#xff0c;肯定会存在深度的调用链路&#xff0c;如果出现BUG或者异常&#xff0c;就会让问题定位和处理效率非常低。 有了Sleuth &#xff0c;就可以帮助我们记录、跟踪应用程序中的请求和操作。…

C++:哈希表的模拟实现

文章目录 哈希哈希冲突哈希函数 解决哈希冲突闭散列&#xff1a;开散列 哈希 在顺序结构和平衡树中&#xff0c;元素的Key和存储位置之间没有必然的联系&#xff0c;在进行查找的时候&#xff0c;要不断的进行比较&#xff0c;时间复杂度是O(N)或O(logN) 而有没有这样一种方案…

数据库基本操作-----数据库用户管理和授权

一、数据库用户管理 1&#xff0e;新建用户 CREATE USER 用户名来源地址 [IDENTIFIED BY [PASSWORD] 密码];‘用户名’&#xff1a;指定将创建的用户名 ‘来源地址’&#xff1a;指定新创建的用户可在哪些主机上登录&#xff0c;可使用IP地址、网段、主机名的形式&#xff0c…

linux下流媒体压力测试工具的使用

前言 因为领导要求做linux的推拉流时服务器压力测试&#xff0c;于是在网上找了找。一顿操作下来&#xff0c;发现很多软件盗用一款名为srs-bench的开源软件。 该代码仓库有详细的使用说明&#xff0c;而且可以在issues中找到可能会遇到的问题的解决办法 需要下载该仓库的源…

C# Onnx 百度PaddleSeg发布的实时人像抠图PP-MattingV2

目录 效果 模型信息 项目 代码 下载 效果 图片源自网络侵删 模型信息 Inputs ------------------------- name&#xff1a;img tensor&#xff1a;Float[1, 3, 480, 640] --------------------------------------------------------------- Outputs -----------------…

ZLMediaKit安装配置和推拉流

一、ZLMediaKit 库简介 ZLMediaKit 是一个基于 C11 的高性能运营级流媒体服务框架 官方写的项目特点&#xff1a; 基于 C11 开发&#xff0c;避免使用裸指针&#xff0c;代码稳定可靠&#xff0c;性能优越。 支持多种协议(RTSP/RTMP/HLS/HTTP-FLV/Websocket-FLV/GB28181/MP…

栈的生长方向不总是向下

据我了解&#xff0c;栈的生长方向向下&#xff0c;内存地址由高到低 测试 windows下&#xff1a; 符合上述情况 测试Linux下&#xff1a; 由此可见&#xff0c;栈在不同操作系统环境下&#xff0c;生长方向不总是向下

【Python】Vscode解决Python中制表符和空格混用导致的缩进问题

【Python】Vscode解决Python中制表符和空格混用导致的缩进问题 文章目录 【Python】Vscode解决Python中制表符和空格混用导致的缩进问题1. 问题来源2. 解决Reference 1. 问题来源 在python中使用缩进来进行代码块的分区&#xff0c;通常来说python的一个缩进包含4个空格&#…

不存在类型变量 A, T 的实例,使 Collector<T, A, List<T>> 符合 Supplier<R>

报错信息 原因: 不存在类型变量 A, T 的实例&#xff0c;使 Collector<T, A, List<\T>> 符合 Supplier<\R> 来源 测试Stream流的map方法&#xff0c;做算法习惯基本类型定义数组。 map方法:Stream API的一部分。允许以一种声明式的方式处理数据&#xff0c…

nodejs搭建本地服务

前端开发时想自己有个本地服务如下操作直接上干货 1.在桌面上直接在powerShell 输入命令行 npm install -g express-generator 然后 npm install -g express 然后新建一个例如server的文件夹 在powerShell执行 express myStudy -e 端口号默认是3000 直接在地址栏输入 http://…

Windows 7 连接 Windows 10 共享打印机,Windows 无法连接打印机,操作失败,错误为0x0000011b 的终极解决办法

Windows 7 连接 Windows 10 共享打印机出现错误 0x000001b&#xff0c;建议不要通过卸载Windows10系统的KB5005565安全更新来解决该问题&#xff08;犹如削足适履&#xff09;&#xff0c;正确的处理方法是手工添加一个本地打印机&#xff0c;本方法是安全可靠的。本文详述了该…

枚举 蓝桥oj DNA序列修正

题目详情&#xff1a; 简单翻译&#xff1a; 主要思路&#xff1a; 1 本题采用贪心思路&#xff0c;要使调整次数最少&#xff0c;就是尽量交换两个碱基对&#xff0c;而不是单个替换&#xff0c;因为本题已经说明只能每个碱基对只能交换一次&#xff0c;所以不考虑A与B交换再…

NC65 修改元数据字段长度

NC65 修改元数据字段长度&#xff0c;执行下面sql&#xff0c;执行完后需要重启NC服务才生效。 --属性 update md_property set attrlength 200 where name fphm and classidece96dd8-bdf8-4db3-a112-9d2f636d388f ;--列 update md_column set columnlength 200 where tab…

远程命令执行漏洞原理,以及防护绕过方式

一、背景 RCE(Remote Command /Code Execute) 远程代码执行漏洞 通过PHP代码注入、Java代码注入等方式连接程序中预留的后门或接口从而进行远程命令执行&#xff0c;达到对服务器的控制。 为什么会出现远程代码执行漏洞呢&#xff1f; Web应用有时需要调用执行一些系统命令函数…

YOLOv5 环境搭建

YOLOv5 环境搭建 flyfish 环境 Ubuntu20.04 驱动、CUDA Toolkit、cuDNN、PyTorch版本对应 1 NVIDIA驱动安装 在[附加驱动界]面安装驱动时&#xff0c;需要输入安全密码&#xff0c;需要记下&#xff0c;后面还需要输入这个密码 重启之后有的机器会出现 perform mok manage…