如果学不会也不要打我。

假设你会线段树

开始!

主席树也叫可持久化线段树

顾名思义,它能够保存线段树在每个时刻的版本。

什么叫每个时刻的版本?你可能对一棵普通线段树进行各种修改,这每种样子就是我们所说的不同时刻的版本。

假设我们对线段树进行单点修改,维护区间和。

每次修改操作中,只有logn个节点会被修改,我们可以复制这些被修改的节点,而不复制没有被改变的节点(以提高效率)。

最后通过特殊的方式建立出新时刻的树。

建造方式如下:

假设上一时刻的树长这样:

现在进行修改操作,对下标为3的位置修改,也就是说修改1 3 6号节点。若是普通线段树,则直接修改1 3 6三个节点。但是在主席树中,我们不直接在1 3 6号节点上修改。而是新建3个节点,分别对应1 3 6号节点,对新建节点进行本想在1 3 6号节点进行的操作(“本想”指普通线段树)。

如图:

关于不同版本的线段树理解

接上图,可以观察到,1号和8号往下分别是两棵不同版本的线段树,不同版本共用很多节点。这并不会影响自上而下的查询。

单点修改的例子

以下内容质量不高:

寒羽吾:

用主席树做kth number,就是在空线段树的基础上,依次在线段树的位置a[1]处加一,a[2]处加一。即用线段树维护值在某区间中的ai有多少个。然后可以在线段树上移动指针,找到第k个。

寒羽吾:

考虑区间[l,r]的限制,即r时刻的线段树减去l-1时刻的线段树,就得到维护ai(下标i在[l,r]中)的线段树了。

寒羽吾:

查询的时候不必真把做差得到的线段树求出来,需要这个线段树的什么位置就访问r版本和l-1版本的对应点,取出值相减即可。

寒羽吾:

上面是我写的板子,t表示树节点,w[0]左孩子w[1]右孩子。

寒羽吾:

理论上维护21e9个元素的线段树是开不下节点的(也是时间上不可建立的),但因为主席树的特殊性:只建立需要用(改变)的节点。所以可以不对ai进行离散化,直接建立“看似”能维护21e9个元素的线段树。

#include<bits/stdc++.h>
using namespace std;
struct node{
int sum;
int w[2];
}t[5000005];
int np;
int n,m;
int st[100005];
int a[100005];
void plu(int x,int c,int num){
int now=++np;
t[now]=t[x];
if(c<0){
t[now].sum++;
return;
}
int p=(num>>c)&1;
plu(t[now].w[p],c-1,num);
t[now].w[p]=now+1;
t[now].sum=t[t[now].w[0]].sum+t[t[now].w[1]].sum;
}
int solve(int l,int r,int k){
int lx=st[l-1],rx=st[r],ans=0;
for(int i=0;i<=30;i++){
int p=0;
if(t[t[rx].w[0]].sum-t[t[lx].w[0]].sum<k)
k-=t[t[rx].w[0]].sum-t[t[lx].w[0]].sum,
p=1;
lx=t[lx].w[p],
rx=t[rx].w[p],
ans=ans<<1|p;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]+=1e9;
}
np=1;st[0]=1;
for(int i=1;i<=n;i++){
st[i]=np+1;
plu(st[i-1],30,a[i]);
}
for(int i=1;i<=m;i++){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",int(solve(l,r,k)-1e9));
}
return 0;
}

可持久化线段树(主席树)快速简洁教程 图文并茂 保证学会。kth number例题的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

随机推荐

  1. mysql 研发规范

    1. 命名    a) 有意义.    b) 数据库.表,都用小写,仅使用下划线和小写字母.    c) 索引以idx_开头.    d) 命名不要过长,尽量少于25个字符.    e) 不要使用保留 ...

  2. ButtonAddListener监听按钮点击事件

    ButtonAddListener监听按钮点击事件 using UnityEngine; using System.Collections; using UnityEngine.UI; using U ...

  3. jQuery.form开发手记

      介绍使用API说明ajaxFormajaxSubmitfieldSerializeresetFormclearFormclearFields参数示例 一般情况下其实提交表单我们将数据$(" ...

  4. 请求网络图片缓存到本地 ,还有一些现成的图片加载框架的使用 Ace网络篇(一)

    现在去买年货~~~~~~ 占坑, 现在来填坑 填完睡觉,感谢这俩月的把自己往死里逼得奋斗从JAVA什么都不懂到现在,做这些也是给在自学路上的新人(我也是菜鸟)一点点我力所能及的帮助,等我水平更高了还会 ...

  5. 机器学习——XGBoost

    基础概念 XGBoost(eXtreme Gradient Boosting)是GradientBoosting算法的一个优化的版本,针对传统GBDT算法做了很多细节改进,包括损失函数.正则化.切分点 ...

  6. socket 客户端和服务端通信

    客户端要连接服务器:首先要知道服务器的IP地址.而服务器里有很多的应用程序,每一个应用程序对应一个端口号 所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址, ...

  7. jquery点滴总结

    1.empty().remove().detach() empty():只移除了 指定元素中的所有子节点,而留下 了<p></p>,仍保留其在dom中所占的位置. remove ...

  8. [转]Newtonsoft.Json高级用法

    本文转自:http://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多 ...

  9. 在windows上用netsh动态配置端口转发

    使用多个虚拟机,将开发环境和工作沟通环境分开(即时通,办公系统都只能在windows下使用…),将开发环境的服务提供给外部访问时,需要在主机上通过代理配置数据转发. VirtualBox提供了端口转发 ...

  10. 归并排序——Java实现

    一.排序思想 将两个或两个以上的一排序文件合并成一个有序文件的过程叫归并,而归并排序就是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用.将以有序的了序列合并,得到完全有序 ...