Luogu P3834

可持久化数据结构就是支持在历史版本上进行查询和修改操作的数据结构。

主席树就是对线段树的改进,使之可持久化。

前置知识:动态开点线段树

我们利用权值(值域)线段树统计区间内的数出现的次数。

(权值线段树类似于线段树+桶)

那么我们可以对每一个位置建立一棵线段树,维护\(1\)~\(i\)的数据在一个区间上出现的次数。

求\(a[l...r]\)第k小,可以令第\(r\)棵线段树在区间\([x,y]\)上出现的次数减去上第\(l-1\)棵的线段树在区间\([x,y]\)上出现的次数,这样就可以得出\(a[l...r]\)在区间\([x,y]\)上出现的次数,如果次数小于\(k\),那么说明第\(k\)大在相邻的下一个区间。

事实上我们不可能对每个位置建立线段树,否则一定会MLE,所以对于这个版本相对于上一个版本没有改变过的节点,我们可以直接使用上一个版本的节点。

结合代码进行理解:

#include<cstdio>
#include<algorithm>
#define mid ((l+r)>>1)
using namespace std;
const int maxn=2e5;
int tot,tree[maxn<<5],ls[maxn<<5],rs[maxn<<5],n,m,a[maxn],b[maxn],rt[maxn],l,r,k;
//rt[]为各个版本的根节点,ls[]为节点的左儿子,rs[]为节点的右儿子
int build(int l,int r)
{
int now=++tot;
if (l==r)
{
tree[now]++;
return now;
}
ls[now]=build(l,mid);
rs[now]=build(mid+1,r);
return now;
}
int update(int root,int l,int r,int pnt)
{
int now=++tot;//新建节点
if (l<=pnt&&pnt<=r)
{
tree[now]=tree[root]+1;//继承信息
ls[now]=ls[root];
rs[now]=rs[root];
//记录左右儿子,假设可以直接使用上一个版本的节点
}
if (l==r) return now;
if (mid>=pnt) ls[now]=update(ls[now],l,mid,pnt);
else rs[now]=update(rs[now],mid+1,r,pnt);
//更新,并更换儿子节点编号
return now;
}
int query(int u,int v,int l,int r,int k)
{
if (l==r) return l;
int tmp=tree[ls[v]]-tree[ls[u]];//计算左区间出现次数
if (tmp>=k) return query(ls[u],ls[v],l,mid,k);
else return query(rs[u],rs[v],mid+1,r,k-tmp);//不在
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];//保存副本供离散化使用
}
sort(b+1,b+1+n);
int newend=unique(b+1,b+1+n)-b-1;
rt[0]=build(1,newend);//首先建立一个空的线段树
for (int i=1;i<=n;i++)
{
int loc=lower_bound(b+1,b+1+newend,a[i])-b;
rt[i]=update(rt[i-1],1,newend,loc);//更新,记录新版本的根节点
}
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&k);
int loc=query(rt[l-1],rt[r],1,newend,k);
printf("%d\n",b[loc]);
}
return 0;
}

【Luogu P3834】可持久化线段树(主席树)的更多相关文章

  1. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  2. [Luogu 3701] 「伪模板」主席树

    [Luogu 3701] 「伪模板」主席树 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 ...

  3. 洛谷P3834 可持久化线段树(主席树)模板

    题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...

  4. 洛谷 [P3834] 可持久化线段树(主席树)

    主席树可以存储线段树的历史状态,空间消耗很大,一般开45n即可 #include <iostream> #include <cstdio> #include <cstri ...

  5. [学习笔记] 可持久化线段树&主席树

    众所周知,线段树是一个非常好用也好写的数据结构, 因此,我们今天的前置技能:线段树. 然而,可持久化到底是什么东西? 别急,我们一步一步来... step 1 首先,一道简化的模型: 给定一个长度为\ ...

  6. 权值线段树&&可持久化线段树&&主席树

    权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...

  7. 【数据结构模版】可持久化线段树 && 主席树

    浙江集训Day4,从早8:00懵B到晚21:00,只搞懂了可持久化线段树以及主席树的板子.今天只能记个大概,以后详细完善讲解. 可持久化线段树指的是一种基于线段树的可回溯历史状态的数据结构.我们想要保 ...

  8. bzoj 4408: [Fjoi 2016]神秘数 数学 可持久化线段树 主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4299 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1 ...

  9. 牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)

    J.Different Integers 题意就是给你l,r,问你在区间两侧的[1,l]和[r,n]中,不同数的个数. 两种思路: 1.将数组长度扩大两倍,for(int i=n+1;i<=2* ...

  10. [POJ2104] K – th Number (可持久化线段树 主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

随机推荐

  1. SpringMVC重点知识总结

    SpringMVC总结 1. SpringMVC简介 MVC即模型-视图-控制器(Model-View-Controller) Spring Web MVC是一种基于Java的实现了Web MVC设计 ...

  2. 数据结构(四十一)多路查找树(B树)

    一.多路查找树的背景 前面所讨论的查找算法都是在内存中进行的,它们适用于较小的文件,而对于较大的.存放在外存储器上的文件就不合适了,对于此类大规模的文件,即使是采用了平衡二叉树,在查找效率上仍然较低. ...

  3. 选择器, ,>,+,~

    一.后代选择器 选取指定元素的后代元素 与子元素选择器相比,后代选择器选取的不一定是直接后代(儿子),而是作用于所有后代元素(儿子.孙子.重孙…)都可以. 二.(>)子元素选择器 选取某个元素的 ...

  4. swift ARC中的strong、weak、unowned

    Swift 用自动引用计数ARC(Automatic Reference Counting)方式来跟踪和管理app的内存使用.这使得内存管理成为swift内部的机制,不需要认为考虑.ARC会自动释放那 ...

  5. HTTP 304状态码的详细讲解

    首先,对于304状态码不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应. 客户端在请求一个文件的时候,发现自己缓存的文件有 Last Modified ,那么在请求中会包含 If Mod ...

  6. Node.js 使用 express-jwt 解析 JWT

    Node.js 上 Token 鉴权常用的是 passport,它可以自定义校验策略,但如果你是用 express 框架,又只是解析 JWT 这种简单需求,可以尝试下 express-jwt 这个中间 ...

  7. Java设计模式:23种设计模式

    1. 软件设计模式概述 2. GoF 的 23 种设计模式的分类和功能 3. UML中的类图及类图之间的关系 4. 开闭原则——面向对象设计原则 5. 里氏替换原则——面向对象设计原则 6. 依赖倒置 ...

  8. python中小整数对象池及intern机制

    小整数对象池: Python为了优化速度,使用了小整数对象池,避免为整数频繁申请和销毁 Python 对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收,所有位于这个范围 ...

  9. 天天玩微信,Spring Boot 开发私有即时通信系统了解一下

    1/ 概述 利用Spring Boot作为基础框架,Spring Security作为安全框架,WebSocket作为通信框架,实现点对点聊天和群聊天. 2/ 所需依赖 Spring Boot 版本 ...

  10. 三分钟学会Redis在.NET Core中做缓存中间件

    大家好,今天给大家说明如何在.NET Core中使用Redis,我们在想要辩论程序的好与坏,都想需要一个可视化工具,我经常使用的是一位国内大牛开发的免费工具,其Github地址为: https://g ...