区间第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.hqwc.cn/news/206332.html

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

相关文章

前缀和的动态维护——树状数组[C/C++]

文章目录 前言lowbitlowbit的定义lowbit的计算 树状数组的思想树状数组的操作单点修改 update前缀查询 query树状数组的建立 build 前言 树状数组巧妙了利用位运算和树形结构实现了允许单点修改的情况下&#xff0c;动态维护前缀和&#xff0c;并且实现单点修改和前缀和查询的效…

如何用CHAT分析网络流行语的构成特点及趋势?

问CHAT&#xff1a;请分析下网络流行语的构成特点及趋势 CHAT回复&#xff1a; 网络流行语的构成特点&#xff1a; 1. 新颖性&#xff1a;网络流行语象征着新潮的概念、思想和观点&#xff0c;它们新颖独特且易于传播。 2. 深入人心的设定&#xff1a;网络流行语通常是由大众…

四川思维跳动商务信息咨询有限公司引领电商服务的先锋

在当今数字化时代&#xff0c;抖音电商作为新型的电子商务模式&#xff0c;已经深入到各个领域。在这个大背景下&#xff0c;四川思维跳动商务信息咨询有限公司以其独特的思维模式和卓越的技术实力&#xff0c;引领着抖音电商服务的发展。 四川思维跳动商务信息咨询有限公司以…

ADManager Plus:全能Active Directory管理的得力助手

一、简介 ADManager Plus是一款功能强大的Active Directory&#xff08;AD&#xff09;管理工具&#xff0c;为企业提供了全面、高效的AD管理解决方案。它不仅简化了AD管理的复杂性&#xff0c;还提高了管理员的工作效率。作为一款综合性的工具&#xff0c;ADManager Plus涵盖…

nohup 实现远程运行不关机操作

nohup 实现远程运行不宕机操作 python nohup 实现远程运行不宕机操作 - python教程网 远程运行最怕断电&#xff0c;训练了几个小时的数据说没就没&#xff0c;或者停止运行。 用nohup 记录代码的输出&#xff0c;还可以不受断电的影响。 方法 1. 用nohup 运行一个python文…

公众号gif图怎么制作?一招三步就能解决

在公众号中添加gif动图可以增加文章的气氛&#xff0c;提高阅读者的兴趣。那么&#xff0c;公众号里的gif动图是怎么制作的呢&#xff1f;给大家分享一款gif动图制作&#xff08;https://www.gif.cn/&#xff09;工具。无需下载软件&#xff0c;上传两张及以上的jpg、png格式图…

飞书多维表格【单选】的排序规则

飞书多维表格的排序竟然不是根据拼音排的&#xff0c;而是根据单选的先后顺序进行排序的。

Python requests请求响应以流stream的方式打印输出

如果你使用的请求库是requests&#xff0c;那么你必须了解的大模型里的请求怎么响应式的接收并打印出来的。 这里给大家写一下正式的书写方式: import requestsurl "http://localhost:8080/stream"payload {} headers {}response requests.request("GET&q…

Linux:进度条(小程序)以及git三板斧

Linux小程序&#xff1a;进度条 在实现小程序前我们要弄清楚&#xff1a; 1.缓冲区&#xff1b; 2.回车与换行。 缓冲区&#xff1a; 分别用gcc来编译下面两个程序&#xff1a; 程序一&#xff1a; #include <stdio.h> int main() { printf("hello Makefil…

Doris数据模型的选择建议(十三)

Doris 的数据模型主要分为 3 类&#xff1a;Aggregate、Uniq、Duplicate Aggregate: Doris 数据模型-Aggregate 模型 Uniq&#xff1a;Doris 数据模型-Uniq 模型 Duplicate&#xff1a;Doris 数据模型-Duplicate 模型 因为数据模型在建表时就已经确定&#xff0c;且无法修改…

[MICROSAR Adaptive] --- Communication Management

0 引言 本期会介绍communicationmanagement通信管理,首先介绍它的特点使用方式,然后介绍模型中的相关元素和c++代码中的相关API,最后我们实现一个应用程序,他有两个Executable组成,一个是提供服务的provider,另一个是使用这个服务的consumer。 1 communication manage…