边刷边更新...
可持久化操作相信大家都不陌生,那么trie树的可持久化其实跟主席树差不多。
那么跟主席树差不多,我们在建树的时候肯定是选择在每次插入的时候值更新改更新的节点,其他的就继承之前的版本就可以了。
这里展示一下01trie的可持久化的建树操作,那么其实普通字符串的也是同理。
解释都放在了代码里。
void insert(int pre,int now,int i,int k)
{//之前版本的根位置,当前版本的根位置,插入的序号,数字遍历到了哪一位(这里是从后往前插入)
if(k<0)
{
last[now]=i;//更新改字符串的最晚插入的版本
return;
}
int id=(mas[i].val>>k)&1;//要插入的是什么字符
if(pre) tr[now][id^1]=tr[pre][id^1];//继承之前的版本
tr[now][id]=++cnt;//新建一个节点
insert(tr[pre][id],tr[now][id],i,k-1);//递归插入字符串
last[now]=max(last[tr[now][0]],last[tr[now][1]]);//更新改字符串的最晚插入的版本
}
接下来考虑怎么遍历。如果是01trie的话,我们还要考虑怎么求异或最大值。想想看普通的trie是怎么求异或最大值的,就是从后往前按位贪心嘛,那么这个也是同理,只不过可持久化的trie可以应用于区间罢了,原理是一样的。但是怎么做到只在要求的区间里面遍历呢?仔细观察一下我上面写的初始化代码,有去维护一个last数组,它的意思是每一个节点最晚在哪一个版本被更新,那么加入我们要查询的版本在【l,r】之间的话,首先从r版本的根位置开始向下查询,肯定是不会超过r的,所以我们只需要关注左边界。那么只要对应的节点的last值>=l,我们不就可以访问了吗,就是这样。
ll query(int l,int r,int val)//查询
{//l是你的左

这篇博客介绍了可持久化Trie树的概念,并通过最大异或和问题及有序序列的次大值异或问题展示了其应用。文章详细阐述了如何建立可持久化Trie树,以及如何进行查询和更新操作,特别提到了在不同场景下利用last数组优化区间查询的方法。
最低0.47元/天 解锁文章
336

被折叠的 条评论
为什么被折叠?



