洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]
可持久化线段树1(主席树)
题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。
输入输出格式
输入格式:
第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个正整数,表示这个序列各项的数字。
接下来M行每行包含三个整数 l,r,kl,r,k , 表示查询区间 [l,r][l,r] 内的第k小值。
输出格式:
输出包含k行,每行1个正整数,依次表示每一次查询的结果
输入输出样例
说明
数据范围:
对于20%的数据满足: 1≤N,M≤101≤N,M≤10
对于50%的数据满足: 1≤N,M≤1031≤N,M≤103
对于80%的数据满足: 1≤N,M≤1051≤N,M≤105
对于100%的数据满足: 1≤N,M≤2⋅1051≤N,M≤2⋅105
对于数列中的所有数 aiai ,均满足 −109≤ai≤109−109≤ai≤109
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为 [25957,6405,15770,26287,26465][25957,6405,15770,26287,26465]
第一次查询为 [2,2][2,2] 区间内的第一小值,即为6405
第二次查询为 [3,4][3,4] 区间内的第一小值,即为15770
第三次查询为 [4,5][4,5] 区间内的第一小值,即为26287
第四次查询为 [1,2][1,2] 区间内的第二小值,即为25957
第五次查询为 [4,4][4,4] 区间内的第一小值,即为26287
分析:
主席树入门题。
一直说要学习主席树来的,但是直到今天才实现。主席树的具体思想蒟蒻就不再赘述,只说下kk小值查询如何实现。查询静态kk小值的时候在主席树中存储的是一个权值,也就是说我们把这棵主席树当做一颗权值树。现将数据离散,然后按照原顺序依次插入线段树中,从根节点开始往下直到找到第该元素排名个数个的线段树中节点的位置,将沿途经过的每个节点的记录的值+1。这样的话根据线段树中的权值就可以用一种类似于平衡树查询kk小值的方法来查询。具体实现看代码。
Code:
- //It is made by HolseLee on 29th July 2018
- //Luogu.org P3834
- #include<bits/stdc++.h>
- using namespace std;
- const int N=2e5+7;
- int n,m,tot,cnt,a[N],b[N],rk[N],rt[N];
- struct President_tree{
- int ls,rs,sum;
- }t[N*20];
- int read()
- {
- char ch=getchar();int num=0;bool flag=false;
- while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
- while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+ch-'0';ch=getchar();}
- return flag?-num:num;
- }
- inline void build(int l,int r,int &node)
- {
- node=++cnt;
- if(l==r)return ;
- int mid=(l+r)>>1;
- build(l,mid,t[node].ls);
- build(mid+1,r,t[node].rs);
- }
- inline void update(int l,int r,int &node,int last,int tar)
- {
- node=++cnt;t[node]=t[last];++t[node].sum;
- if(l==r)return;
- int mid=(l+r)>>1;
- if(tar<=mid)update(l,mid,t[node].ls,t[last].ls,tar);
- else update(mid+1,r,t[node].rs,t[last].rs,tar);
- }
- inline int quary(int l,int r,int node,int last,int tar)
- {
- if(l==r)return a[l];
- int now=t[t[node].ls].sum-t[t[last].ls].sum,mid=(l+r)>>1;
- if(tar<=now)return quary(l,mid,t[node].ls,t[last].ls,tar);
- else return quary(mid+1,r,t[node].rs,t[last].rs,tar-now);
- }
- int main()
- {
- n=read();m=read();
- for(int i=1;i<=n;++i){
- a[i]=read();b[i]=a[i];
- }
- sort(a+1,a+n+1);
- tot=unique(a+1,a+n+1)-a-1;
- build(1,tot,rt[0]);
- for(int i=1;i<=n;++i)
- rk[i]=lower_bound(a+1,a+tot+1,b[i])-a;
- for(int i=1;i<=n;i++)
- update(1,tot,rt[i],rt[i-1],rk[i]);
- int l,r,k;
- for(int i=1;i<=m;++i){
- l=read();r=read();k=read();
- printf("%d\n",quary(1,tot,rt[r],rt[l-1],k));
- }
- return 0;
- }
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)