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」数据结构方向 - 可持久化数据结构的更多相关文章

  1. 「NOTE」常系数齐次线性递推

    要不是考到了,我还没发现这玩意我不是很会-- # 前置 多项式取模: 矩阵快速幂. # 常系数齐次线性递推 描述的是这么一个问题,给定数列 \(c_1,c_2,\dots,c_k\) 以及数列 \(f ...

  2. LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集

    把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...

  3. 「HNOI2016」数据结构大毒瘤

    真是 \(6\) 道数据结构毒瘤... 开始口胡各种做法... 「HNOI2016」网络 整体二分+树状数组. 开始想了一个大常数 \(O(n\log^2 n)\) 做法,然后就被卡掉了... 发现直 ...

  4. 「luogu3402」【模板】可持久化并查集

    「luogu3402」[模板]可持久化并查集 传送门 我们可以用一个可持久化数组来存每个节点的父亲. 单点信息更新和查询就用主席树多花 一个 \(\log\) 的代价来搞. 然后考虑如何合并两个点. ...

  5. Note -「多项式」基础模板(FFT/NTT/多模 NTT)光速入门

      进阶篇戳这里. 目录 何为「多项式」 基本概念 系数表示法 & 点值表示法 傅里叶(Fourier)变换 概述 前置知识 - 复数 单位根 快速傅里叶正变换(FFT) 快速傅里叶逆变换(I ...

  6. 「SOL」JOISC2021 解题报告

    JOIS(egment-Tree)C 1. 前言 很早之前教练让我们做这套题,我以为这套题应该挺简单,用几天的空余时间就能刷完,结果预想的短周期刷题变成了长周期刷题--(好像是整个团队里最后一个刷完的 ...

  7. LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)

    题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...

  8. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  9. 「MoreThanJava」当大学选择了计算机之后应该知道的

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  10. 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...

随机推荐

  1. [Qt基础-06] QButtonGroup

    QButtonGroup 本文主要根据QT官方帮助文档以及日常使用,简单的介绍一下QButtonGroup的功能以及基本使用 文章目录 QButtonGroup 简介 信号和槽 简介 有的时候,我们会 ...

  2. 如何解决ubuntu安装第三方deb出现的read unknown VMA问题(SUID sandbox配置问题)

    前言 众所不周知,ubuntu的snap有些让人无语凝噎的问题,比方说如果你在Ubuntu 24.04 LTS通过它安装vscode,恭喜你,你无法在vscode中输入中文,缘由不明,又或者对于str ...

  3. 鸿蒙开发 HarmonyOS DevEco Studio 常用快捷键

    前言 做 HarmonyOS 鸿蒙开发离不开 DevEco Studio 开发工具, DevEco Studio 是基于 IntelliJ IDEA Community 开源版本打造,所以默认的快捷键 ...

  4. Golang 入门 : 语言环境安装

    下载介绍 在go的官方网址上下载go最新版本https://golang.google.cn/dl/,或者在 Go 的中文网上下载https://studygolang.com/dl,两个网站打开的内 ...

  5. BandiZip无广告版安装

    BandiZip无广告版安装 Bandizip 是一款压缩软件,它支持Zip.7-Zip 和 RAR 以及其它压缩格式.它拥有非常快速的压缩和解压缩的算法,从大学用到现在,但是现在最新的版本在每次压缩 ...

  6. 用于线程同步的Interlocked系列函数主要有哪些

    原子访问 通过Interlocked系列函数是 Windows API 提供的一组原子操作函数,用于在多线程环境中安全地操作共享变量.当我们执行这些Interlocked系列函数的时候 ,函数会对总线 ...

  7. Let’s Encrypt & Certbot 浅谈

    前言 当我们想给网站启用HTTPS, 通常需要从证书颁发机构购买证书, 并配置到现有的HTTP服务上来实现HTTPS. 这里暗藏的痛点是: 我们需要花钱(买证书) 证书颁发机构(质量参差不齐, 不一定 ...

  8. unigui的错误delphi clientHeight:property clientheight does not exist【10】

    在unigui运行中发现这样的错误clientHeight:property clientheight does not exist. 这是啥原因.从老版本中复制过来的代码含dfm会出现这样的错误. ...

  9. Codeforces Round 1016 (Div. 3)题解

    题目地址 https://codeforces.com/contest/2093 锐评 在所有题意都理解正确的情况下,整体难度不算太难.但是偏偏存在F这么恶心的题意,样例都不带解释一下的,根本看不懂题 ...

  10. java程序乱码问题

    1.字符编码简介 字符编码从字面上理解,就是将字符编码为由多个bits(0或1)组成的字节序列.但字符和字节序列的映射并不是直接的,可简要概括为2个步骤,第1步由字符映射到unicode码,第2步由u ...