trie树(三) 可持久化

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

边刷边更新...

可持久化操作相信大家都不陌生,那么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是你的左
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值