前言
不得不说,可持久化数据结构真是太难了!
由于数据结构这东西真的太玄学了,学这个主席树我真的学了很久。
简介
主席树为什么叫主席树?据说因为它是一个名字缩写为 H J T HJT HJT的神犇发明的,与当时主席的名字缩写一样…
主席树实质上就是一棵可持久化线段树,它的具体实现可以看下面。
让我们从值域线段树开始说起
要学主席树,我们就要先学值域线段树。
值域线段树的区间存的并不是节点信息,而是在值在某一范围内的数的个数。
如图就是一棵值域线段树,其中1号节点存储的是大于等于1小于等于4的数字个数,2号节点存储的是大于等于1小于等于2的数字个数,3号节点存储的是大于等于3小于等于4的数字个数,4号节点存储的是等于1的数字个数,5号节点存储的是等于2的数字个数,6号节点存储的是等于3的数字个数,7号节点存储的是等于4的数字个数。
值域线段树的查询也挺简单的,若要查询这段区间内的第 k k k大,只要比较当前元素的左子树大小加1(1是当前元素本身的大小)与询问的 k k k,若大于等于,就访问左子树,否则将 k k k减去当前元素的左子树大小加1,然后访问右子树。
这和平衡树有什么区别!!!
还有一个问题,就是值域线段树存储的区间范围是固定的,所以如果要查询区间第 k k k大,我们就不能只用一棵值域线段树。
考虑建 n n n棵值域线段树,每棵值域线段树存储区间 [ 1 , i ] [1,i] [1,i]的信息,这样一来,要查询 [ l , r ] [l,r] [l,r]的第 k k k大时,只要在查询的过程中,将第 r r r棵值域线段树的信息减去第 l − 1 l-1 l−1棵值域线段树的信息即可,这利用了前缀和的思想。
或许你会问,这有什么用?建 n n n棵树,内存那么大,我平衡树第一个不服!
好吧,不服就不服,值域线段树还是有点用的,因为平衡树没法可持久化啊(**可持久化 T r e a p Treap Tr