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

news2024/9/26 5:23:04

 题意:多次询问,每次询问某区间的第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.coloradmin.cn/o/1243367.html

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

相关文章

Shopee本土号封号几率大吗?如何避免封号?被封号了怎么办?

Shopee是近几年热门的电商平台之一&#xff0c;即使越来越多的跨境电商涌现&#xff0c;他的地位在东南亚市场依然占据一席之地&#xff0c;也依旧吸引着需要跨境商家入局。尤其在2023年&#xff0c;在TikTok Shop在印尼被关停之后&#xff0c;留下了大片空白&#xff0c;Shope…

如何解决tinder注册失败的问题?

tinder创立在2012年&#xff0c;是一款海外热门的交友软件。2020年&#xff0c;Tinder拥有620万用户和7500万月活跃用户。截至2021年&#xff0c;Tinder在全球范围内的匹配记录超过650亿。已成为全球最受欢迎的约会软件之一。 目前tinder暂时未对中国大陆开发使用&#xff0c;…

Python入门教程 | Python3 字典(dict)

Python3 字典 字典是另一种可变容器模型&#xff0c;且可存储任意类型对象。 Python3中的字典是一种无序、可变、可迭代的数据结构&#xff0c;它由键&#xff08;key&#xff09;和对应的值&#xff08;value&#xff09;组成。字典在Python中被视为可变对象&#xff0c;这意…

多级缓存快速上手

哈喽~大家好&#xff0c;这篇来看看多级缓存。 &#x1f947;个人主页&#xff1a;个人主页​​​​​ &#x1f948; 系列专栏&#xff1a;【微服务】 &#x1f949;与这篇相关的文章&#xff1a; JAVA进程和线程JAVA进程和线程-CSDN博客Http…

【数据结构/C++】栈和队列_链队列

#include <iostream> using namespace std; // 链队列 typedef int ElemType; typedef struct LinkNode {ElemType data;struct LinkNode *next; } LinkNode; typedef struct {LinkNode *front, *rear; } LinkQueue; // 初始化 void InitQueue(LinkQueue &Q) {Q.fron…

Redis深入理解-Socket连接建立流程以及文件事件处理机制

Redis Server 运行原理图 Redis 服务器中 Socket 网络建立以及文件事件模型 一个 redis 单机&#xff0c;可以抗几百上千的并发&#xff0c;这里的并发指的就是同时可以有几百个 client 对这个 redis server 发起请求&#xff0c;都需要去建立网络连接&#xff0c;同时间可能会…

Attention is All You Need:Transformer各模块详解

Transformer encoder-decoder架构 Encoder&#xff1a;将输入序列转换为一个连续向量空间中的表示。Encoder通常是一个循环神经网络&#xff08;RNN&#xff09;或者卷积神经网络&#xff08;CNN&#xff09;&#xff0c;通过对输入序列中的每个元素进行编码&#xff0c;得到…

SQLite3 数据库学习(六):Qt 嵌入式 Web 服务器详解

参考引用 SQLite 权威指南&#xff08;第二版&#xff09;SQLite3 入门 1. Apache 搭建 cgi 环境 1.1 什么是 Apache Apache 是世界使用排名第一的 Web 服务器软件 它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;由于其跨平台和安全性被广泛使用 1.2 具体搭建流程…

代码随想录算法训练营Day 59 || 503.下一个更大元素II、42. 接雨水

503.下一个更大元素II 力扣题目链接(opens new window) 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更…

数据中台建设方法论

1、数仓的概念和了解--业务的痛点 产生的痛点&#xff1a;数据资产比较模糊、数据的质量比较低、重复建设、代码的耦合性比较强。 2、数据仓库中的常见的模型&#xff1a; 1、心型模型&#xff1a;中间是一张事实表&#xff0c;周围都是维度表。 对于心型模型的主要的特点&a…

可上手 JVM 调优实战指南

文章目录 为什么要学 JVM一、JVM 整体布局二、Class 文件规范三、类加载模块四、执行引擎五、GC 垃圾回收1 、JVM内存布局2 、 JVM 有哪些主要的垃圾回收器&#xff1f;3 、分代垃圾回收工作机制 六、对 JVM 进行调优的基础思路七、 GC 情况分析实例八、最后总结 全程可上手JVM…

快速了解敏捷测试!解密敏捷测试的难点!

随着敏捷开发模式的普及&#xff0c;越来越多的测试同仁也开始了敏捷测试。那么究竟什么是敏捷测试&#xff1f;敏捷测试与传统测试的主要区别是什么&#xff1f;敏捷测试的难点又是什么&#xff1f;本文会对这三个问题进行讲解。注意&#xff1a;本文只是讲解敏捷测试概念相关…

String 、StringBuffer 和 StringBuilder 的区别?

String 使用 String 声明一个字符串的时候&#xff0c;该字符串会存放在堆中的字符串常量池中。因为在java中所有的String 都是以常量表示&#xff0c;且由 final 修饰&#xff0c;因此在线程池中它的线程是安全的 且 不可变的 。每个 String 在被创建后就不再发生任何变化。 …

新王加冕,GPT-4V 屠榜视觉问答

当前&#xff0c;多模态大型模型&#xff08;Multi-modal Large Language Model, MLLM&#xff09;在视觉问答&#xff08;VQA&#xff09;领域展现了卓越的能力。然而&#xff0c;真正的挑战在于知识密集型 VQA 任务&#xff0c;这要求不仅要识别视觉元素&#xff0c;还需要结…

【SpringMVC】 对请求的不同响应

前言 本文学习如何运用不同的注解来返回不同的响应. 1.返回静态页面Controller 返回index.html页面 Controller 和 RestController的区别 controller 只有加上这个注解,Spring才会帮我们管理这个代码.后续我们访问时才能访问到. RestController 等同于 Controller ResponseBo…

前端学习--React(3)

一、Redux 集中状态管理工具&#xff0c;不需要react即可使用&#xff0c;每个store的数据都是独立于组件之外的 vue小链接&#xff1a;vuex/pinia 基本使用 Redux将数据修改流程分成三个概念&#xff0c;state、action和reducer state - 一个对象 存放我们管理的数据状态 a…

EI论文故障识别程序:DBN深度置信/信念网络的故障识别Matlab程序,数据由Excel导入,直接运行!

​适用平台&#xff1a;Matlab2021b版及以上 本程序参考中文EI期刊《基于变分模态分解和改进灰狼算法优化深度置信网络的自动转换开关故障识别》中的深度置信网络&#xff08;Deep Belief Network&#xff0c;DBN&#xff09;部分进行故障识别&#xff0c;程序注释清晰&#x…

OpenStack云计算平台-Networking 服务

目录 一、网络服务概览 二、网络&#xff08;neutron&#xff09;概念 三、安装并配置控制节点 1、先决条件 2、配置网络选项&#xff08;公共网络&#xff09; &#xff08;1&#xff09;安装组件 &#xff08;2&#xff09;配置服务组件 &#xff08;3&#xff09;配…

Notepad-- ubuntu下载安装

Notepad-- ubuntu下载安装 下载 Gitee链接&#xff1a; https://gitee.com/cxasm/notepad– 安装 sudo apt install *.deb运行 /opt/apps/com.hmja.notepad/files/Notepad--出错 需要安装qt5 sudo apt-get install qt5-default