P4735 最大异或和 (可持久化01trie)

传送门

在这里插入图片描述

用pre[i]保存前缀异或值,
询问操作就转化为了:
x ^ pre[n] ^ pre[p-1]的最大值,其中l-1<=p-1<=r-1
x^pre[n]是常数,所以问题实质就是在给定区间中询问区间元素与一个常数异或的最大值。01字典树的经典老活的区间询问版本。

对pre数组每个前缀建01字典树,每个节点保存有多少个这样的前缀,由于每次只用1个数(二进制串)去更新一条新链,所以用线段树合并的思想利用上一个版本的树去建树,这和主席树的思想如出一辙。询问[l,r]区间就用root[r]版本减去root[l-1]版本,由于节点存的是相同前缀的数量,所以是有可减性的。

不过可持久化01trie的实现和主席树还是有一些不同的。
首先:
①0这个数要作为第0个版本插入,主席树的话0版本可以默认为0,直接从1开始
②由于字典树的根节点是不保留信息的,所以我们递归的时候每次是更新孩子节点。

在这里插入图片描述

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
const int maxn = 6e5 + 10;
const ll mod = 998244353;
const ll inf = (ll)4e17+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b){
   if(b==1)return 1;return(mod-mod/b)*inv(mod%b)%mod;}
inline ll read()
{
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值