【暖*墟】 #数据结构进阶# 主席树超详细解释

主席树【可持久化线段树/函数式线段树/n棵线段树】

         目录

一. 概念理解

1.求所有数字中的第k大数?

2.求任意一段区间 [ L , r ]中的第k大数?

3.会不会空间超限?

超级详细的实现过程分析【戳我戳我qwq】

二. 例题演练

1 【主席树】第K小的数Ⅰ(caioj1441)

2 【主席树】第K小的数Ⅱ(caioj1442)

3 【主席树】第K小的数Ⅲ(caioj1443)

4 【主席树】逆序对数(caioj1444)

5【主席树】去月球(caioj1447)


一. 概念理解

  • 离线数据结构
  • 可以查询区间第k大
  • 复杂度log(n)

1.求所有数字中的第k大数

先将所有数字离散化【排序+去重】(所以是离线)。

对离散化后的数字建立一颗线段树,每个节点【 统计当前范围内的数的个数 】

自顶向下查找,如果左边区间个数大于等于k则在左边,小于则在右边(从大到小排序)。

2.求任意一段区间 [ L , r ]中的第k大数

建立n棵线段树,每棵维护 [ 1 , i ] 的数字出现情况。

则 [ L , R ] = [ 1 , R ] - [ 1 , L - 1 ] (前缀和思想)。

3.会不会空间超限

n棵线段树,每棵2n个点,怎么也是n^2的空间?

优化方法:注意到每棵新树都转移到上一棵树,只是改了一条从某叶子到根节点的路径 。

那么除了这条路径,其他的都可以直接从上一棵树上转移过来

大概就长这样了 ↓↓↓ 总共只用维护一棵树。空间复杂度O(nlogn)。

( 这个添加过程可以看做是:“链ys”加入“初始树xs”,即加入第一个元素 f 的过程 )

(d',g',f'都是新树相对于原树有修改的点,增加结点编号,把新旧结点都储存下来 )

 

当然,看到这里还是难以理解(反正本蒟蒻是没懂qaq

那就让本蒟蒻手动模拟一下试试吧...(像素渣&&字渣无误)

  • 以序列 4 1 3 2 为例,查询区间 [ 2,4 ] 中第3小的数。

用num[ ]记录原序列。首先“离散化+排序判重”,得到排序后的s数组 1 2 3 4 。

先确定初始线段树状态,再按照num[ ]的顺序,将 4 1 3 2 依次存入线段树中。

ONE POINT{很重要的理解}:下图圆圈内的数就是线段树存的权值,代表着:

统计(按照排名记录的区间)区间 [ i , j ] 中,已经存入的原序列的数(num[ ])的个数。

底层叶子节点记录的是,这个排名位置的数是否已经在树中建立。

0代表还没有建立,1表示已经建立,同时关联的上方管理数组的权值也会相应改变。

下面来模拟建树过程——

(状态1)原始空线段树,所有点的权值都为零。

(状态2)插入num[1]=4,到排序后它应该在的4号位置(是第四小的数)。

第一棵修改树可以用根节点序号标记为root[1]=8(具体root的实现看后面)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值