可持久化Trie树(字典树)

发布时间 2023-12-05 11:57:21作者: 长大想当太空人

举例子:

插入cat:

插入cup:

插入soup:

插入cut:

可持久化数据结构的重要问题就是解决区间的查询问题:

例题,洛谷4735:

 

M个操作,

操作1:添加操作,添加一个树x,序列长度+1

操作2:询问操作,找到一个位置p,满足l<=p<=r,使得a[p] ^ a[p+1] ^ ... ^ a[N] ^ x 最大,输出最大值

 

分析:

令S[k] = a[1] xor a[2] xor ... xor a[k]

  a[p] xor a[p+1] xor ... xor a[N] xor x

=(a[1] xor a[2] xor ... xor a[p-1])  xor (a[1] xor a[2] xor ... xor a[N]) xor x

=s[p-1] xor s[N] xor x

(p = 1时,a[1] xor a[2] xor ... xor a[N] xor x = s[0] xor s[N] xor x,所以s[0] = 0)

又因为s[N] xor x是定值,设为v

此时查询转变为:求一个p∈[l-1,r-1] 使得 s[p] ^ x 最大

 

思路:

构建一个可持久化0/1Trie树,第i个版本为插入了s[i]后的Trie树

每次查询,从根节点开始,贪心地选与这一位相反的值

先考虑查询[1,r]的区间,即查询[0,r-1]的区间,只需要拿出版本为r-1的Trie树,按照上面的贪心方法,即可得到[0,r-1]区间内与定值v的异或最大值

再考虑查询[l,r]的区间,即查询[l-1,r-1]的区间,依然可以拿出版本为r-1的Trie树,查询的时候尽量向着相反的方向跳,但不能超过左侧边界l-1,对每个节点维护一个ver

ver[i]表示第一次被创建的版本。这样,在查询时只访问ver>=l1的节点就行了。

 ver[0]代表所有的不能走的空结点,因为不能走,所以要比最小的l-1(0)要小,这样就会在判断l-1时条件时候避免走空结点,设为-1