算法主席树

Posted oyiya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法主席树相关的知识,希望对你有一定的参考价值。

这是一篇有关主席树的总结

主席树是什么?

对于原序列的每一个前缀[1···i]建立出一棵线段树维护值域上每个数出现的次数,则其树是可减的

PS:本篇随笔对于主席树的基本内容并没有深刻讲解,主要说明它的一些用法

其实就是很多一堆大量的权值线段树

(什么是权值线段树?就是每个节点维护不是位置,而是权值,比如 \\([1,4]\\) 维护的就是权值等于1到权值等于4的信息)

而且这些线段树还隐含了一个前缀和的功能

最简单的就是一个数列,长度为 \\(n\\) ,那么就建 \\(n\\) 棵权值线段树,第 \\(i\\) 棵权值线段树对应第 \\(i\\) 个数,存的是从第一个数到第 \\(i\\) 个数的信息(建第 \\(i\\) 棵权值线段树的时候,只要先把第 \\(i-1\\) 棵权值线段树复制一份,再把 \\(i\\) 位置上的信息加入中间就可以了)

那么我们如果要知道数列中 \\(l\\) 位置到 \\(r\\) 位置的数的信息,就只要把 \\(r\\) 上的权值线段树减去 \\(l-1\\) 的权值线段树,得到的线段树保存的就是 \\(l\\)\\(r\\) 的信息(其实就是一个差分)

然后我们发现每次都新建整个权值线段树又耗时间又爆内存,并且相邻两棵线段树之间改变的只有一点点内容,其它的都没有变,那对于这些不变的节点就不新建了,直接共用,即多棵权值线段树在某个位置共用一个节点

个人认为,主席树就是共用节点的权值线段树

主席树可以用来干嘛?

主席树的所有操作,基本上都可以说是对应一段区间,那么就都要先差分一下,以下所有功能都是差分之后的

  1. 查询区间Kth(第 \\(k\\) 大/小)

    主席树中记录的是 \\(num\\) ,即每个数字出现的次数,然后每次判断当前区间的左子树的 \\(num\\) 是否满足条件,再决定走左子树还是右子树(极其类似于Treap)

  2. 查询区间出现数字的和

    这只要把上面的 \\(num\\) 变成 \\(val\\) ,然后把差分后根节点的 \\(val\\) 输出就行了

  3. 查询区间中权值在 \\([l,r]\\) 之间的所有数字的和

    \\(num\\) 变成了 \\(val\\) 后,不直接返回根节点的值,而是返回主席树上 \\([l,r]\\) 区间的 \\(val\\) 值(因为主席树是权值线段树)

暂知的作用就这几个

几个小套路

  • 如果没有修改只有询问操作,那么可以直接静态主席树。但如果有修改操作,那么就要变成动态了。也就是说我们要有一个东西,可以维护能够修改的前缀和,那就BIT(树状数组)。所以动态主席树,一般就是树状数组套主席树的树套树

  • 如果不是一个数列,而是一棵树上要维护两个节点的信息,那么就把主席树的每个版本变成从父亲继承的就行了,最后的查询就树上差分

这些套路要在题目之中去理解

几道练习题

大体上从简到难(看个人理解)

七道题,后面的神题做得心累

没有数论题好做啊

从未结束

从此,主席树的学习告一段落

HNOI就要到了,可是HNOI最喜欢考的数据结构我还有很多没搞定

下一步——LCT

以上是关于算法主席树的主要内容,如果未能解决你的问题,请参考以下文章

主席树(入门篇)

待修改主席树 (树状数组+主席树)

主席树(可持久化线段树)

算法总结——主席树(poj2104)

主席树

UESTC2021暑假前集训(主席树)