「Note」数据结构方向 - 可持久化数据结构
1. 可持久化线段树
1.1. 简介
可持久化线段树一般用于解决区间第 \(k\) 小值的询问。
首先考虑简化过的问题,区间 \(\left[1,r\right]\) 的第 \(k\) 小值。
考虑用权值线段树(离散化或动态开点)来求 \(k\) 小值,接下来只需要解决区间的问题。
可持久化线段树核心思想:每次插入值时保留历史版本,来实现区间查询第 \(k\) 小。若每次修改暴力地复制一颗线段树显著不可行,考虑到每次修改最多影响 \(\log n\) 级别个数的节点,我们将这些受影响的节点分离出来进行建树,如下图(源于 OI-wiki)。

我们按顺序一个一个插入值,对于区间 \(\left[1,r\right]\) 的第 \(k\) 小值,只需要访问插入第 \(r\) 个值后的那个版本即可。
至于区间 \(\left[l,r\right]\) 的第 \(k\) 小值,只需要使用区间 \(\left[1,r\right]\) 的信息减去区间 \(\left[1,l-1\right]\) 的信息便可求出。
1.2. 例题
\(\color{royalblue}{P3834}\)
板子。
$\text{Code}$:
```
#include
#define LL long long
#define UN unsigned
using namespace std;
//--------------------//
//IO
inline int rd()
{
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
//--------------------//
const int N=2e5+5;
int n,m;
int s[N];
int tcnt,tem[N],id[N];
//--------------------//
const int TN=64e5+5;
struct Seg_Tree
{
struct Seg_Tree_Node
{
int ls,rs;
int val;
}t[TN];
int root[N],tot=0;
void build(int &rt,int L,int R)
{
rt=++tot;
if(LR)
return;
int mid=L+R>>1;
build(t[rt].ls,L,mid);
build(t[rt].rs,mid+1,R);
return;
}
void change(int &rt,int lst,int L,int R,int pos)
{
rt=++tot;
t[rt]=t[lst];
t[rt].val++;
int mid=L+R>>1;
if(LR)
return;
if(pos<=mid)
change(t[rt].ls,t[lst].ls,L,mid,pos);
else
change(t[rt].rs,t[lst].rs,mid+1,R,pos);
return;
}
int query(int rt,int pre,int L,int R,int rk)
{
if(L==R)
return L;
int mid=L+R>>1;
if(rk<=t[t[rt].ls].val-t[t[pre].ls].val)
return query(t[rt].ls,t[pre].ls,L,mid,rk);
return query(t[rt].rs,t[pre].rs,mid+1,R,rk-(t[t[rt].ls].val-t[t[pre].ls].val));
}
}T;
//--------------------//
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]),tem[++tcnt]=s[i];
sort(tem+1,tem+tcnt+1);
tcnt=unique(tem+1,tem+tcnt+1)-tem-1;
T.build(T.root[0],1,tcnt);
for(int temp,i=1;i<=n;i++)
{
temp=lower_bound(tem+1,tem+tcnt+1,s[i])-tem;
id[temp]=s[i];
s[i]=temp;
T.change(T.root[i],T.root[i-1],1,tcnt,s[i]);
}
for(int l,r,rk,i=1;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&rk);
printf("%d\n",id[T.query(T.root[r],T.root[l-1],1,tcnt,rk)]);
}
return 0;
}
</details>
「Note」数据结构方向 - 可持久化数据结构的更多相关文章
- 「NOTE」常系数齐次线性递推
要不是考到了,我还没发现这玩意我不是很会-- # 前置 多项式取模: 矩阵快速幂. # 常系数齐次线性递推 描述的是这么一个问题,给定数列 \(c_1,c_2,\dots,c_k\) 以及数列 \(f ...
- LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集
把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...
- 「HNOI2016」数据结构大毒瘤
真是 \(6\) 道数据结构毒瘤... 开始口胡各种做法... 「HNOI2016」网络 整体二分+树状数组. 开始想了一个大常数 \(O(n\log^2 n)\) 做法,然后就被卡掉了... 发现直 ...
- 「luogu3402」【模板】可持久化并查集
「luogu3402」[模板]可持久化并查集 传送门 我们可以用一个可持久化数组来存每个节点的父亲. 单点信息更新和查询就用主席树多花 一个 \(\log\) 的代价来搞. 然后考虑如何合并两个点. ...
- Note -「多项式」基础模板(FFT/NTT/多模 NTT)光速入门
进阶篇戳这里. 目录 何为「多项式」 基本概念 系数表示法 & 点值表示法 傅里叶(Fourier)变换 概述 前置知识 - 复数 单位根 快速傅里叶正变换(FFT) 快速傅里叶逆变换(I ...
- 「SOL」JOISC2021 解题报告
JOIS(egment-Tree)C 1. 前言 很早之前教练让我们做这套题,我以为这套题应该挺简单,用几天的空余时间就能刷完,结果预想的短周期刷题变成了长周期刷题--(好像是整个团队里最后一个刷完的 ...
- LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)
题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...
- Loj #3055. 「HNOI2019」JOJO
Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...
- 「MoreThanJava」当大学选择了计算机之后应该知道的
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!
「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...
随机推荐
- [Qt基础-06] QButtonGroup
QButtonGroup 本文主要根据QT官方帮助文档以及日常使用,简单的介绍一下QButtonGroup的功能以及基本使用 文章目录 QButtonGroup 简介 信号和槽 简介 有的时候,我们会 ...
- 如何解决ubuntu安装第三方deb出现的read unknown VMA问题(SUID sandbox配置问题)
前言 众所不周知,ubuntu的snap有些让人无语凝噎的问题,比方说如果你在Ubuntu 24.04 LTS通过它安装vscode,恭喜你,你无法在vscode中输入中文,缘由不明,又或者对于str ...
- 鸿蒙开发 HarmonyOS DevEco Studio 常用快捷键
前言 做 HarmonyOS 鸿蒙开发离不开 DevEco Studio 开发工具, DevEco Studio 是基于 IntelliJ IDEA Community 开源版本打造,所以默认的快捷键 ...
- Golang 入门 : 语言环境安装
下载介绍 在go的官方网址上下载go最新版本https://golang.google.cn/dl/,或者在 Go 的中文网上下载https://studygolang.com/dl,两个网站打开的内 ...
- BandiZip无广告版安装
BandiZip无广告版安装 Bandizip 是一款压缩软件,它支持Zip.7-Zip 和 RAR 以及其它压缩格式.它拥有非常快速的压缩和解压缩的算法,从大学用到现在,但是现在最新的版本在每次压缩 ...
- 用于线程同步的Interlocked系列函数主要有哪些
原子访问 通过Interlocked系列函数是 Windows API 提供的一组原子操作函数,用于在多线程环境中安全地操作共享变量.当我们执行这些Interlocked系列函数的时候 ,函数会对总线 ...
- Let’s Encrypt & Certbot 浅谈
前言 当我们想给网站启用HTTPS, 通常需要从证书颁发机构购买证书, 并配置到现有的HTTP服务上来实现HTTPS. 这里暗藏的痛点是: 我们需要花钱(买证书) 证书颁发机构(质量参差不齐, 不一定 ...
- unigui的错误delphi clientHeight:property clientheight does not exist【10】
在unigui运行中发现这样的错误clientHeight:property clientheight does not exist. 这是啥原因.从老版本中复制过来的代码含dfm会出现这样的错误. ...
- Codeforces Round 1016 (Div. 3)题解
题目地址 https://codeforces.com/contest/2093 锐评 在所有题意都理解正确的情况下,整体难度不算太难.但是偏偏存在F这么恶心的题意,样例都不带解释一下的,根本看不懂题 ...
- java程序乱码问题
1.字符编码简介 字符编码从字面上理解,就是将字符编码为由多个bits(0或1)组成的字节序列.但字符和字节序列的映射并不是直接的,可简要概括为2个步骤,第1步由字符映射到unicode码,第2步由u ...