可持久化 Trie

可持久化 Trie

Trie 树的可持久化思路与线段树/平衡树类似,每次都 clone 一个新的节点即可。

唯一需要注意的是实现上的问题,因为 Trie 树一般不写递归,因此要注意实现。

一般实现的可持久化 Trie 都是 01Trie。

Luogu P4735 最大异或和

给定一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\)\(m\) 次操作:

  • 给定 \(x\),在序列末尾加入 \(x\)
  • 给定 \(l,r,x\),对于 \(l\leq i\leq r\),输出 \(a_i\oplus a_{i+1}\oplus\cdots\oplus a_n\oplus x\) 的最大值。

显然可以维护前缀异或和 \(s_1,s_2,\cdots,s_n\),即对于 \(i\in[l,r]\),求 \(x\oplus s_n\oplus s_{i-1}\) 最大值。

发现 \(x\oplus s_n\) 为定值,考虑 01Trie 查询 \(s_{i-1}\)

但是需要区间查询,可以使用可持久化 01Trie,加入一个数即一个新版本。

查询时,前缀和差分即可判断存不存在 \(0\)\(1\)

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=3e5,V=30;
int n;
struct trie{
	int size,root[N<<1|1];
	struct node{
		int m[2];
		int value;
	}t[N*100+1];

	trie(){
		size=1;
		root[0]=1;
	}
	
	int clone(int p){
		t[++size]=t[p];
		return size;
	}
	void insert(int v,int i,int x){
		int p=root[i]=clone(root[v]);
		for(int j=V;j>=0;j--){
			int bit=x>>j&1;
			t[p].m[bit]=clone(t[p].m[bit]);
			p=t[p].m[bit];
			t[p].value++;
		}
	}
	int query(int l,int r,int x){
		int p=root[r],q=root[l-1];
		int ans=0;
		for(int i=V;i>=0;i--){
			int bit=x>>i&1;
			if(t[t[p].m[!bit]].value-t[t[q].m[!bit]].value){
				p=t[p].m[!bit];
				q=t[q].m[!bit];
				ans|=1<<i;
			}else{
				p=t[p].m[bit];
				q=t[q].m[bit];
			}
		}
		return ans;
	}
}t;
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int m;
	cin>>n>>m;
	int s=0;
	t.insert(0,1,0);
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		s^=x;
		t.insert(i,i+1,s);
	}
	while(m--){
		char op;
		int l,r,x;
		cin>>op;
		switch(op){
			case 'A':
				int x;
				cin>>x;
				s^=x;
				n++;
				t.insert(n,n+1,s);
				break;
			case 'Q':
				cin>>l>>r>>x;
				cout<<t.query(l,r,x^s)<<'\n';
				break;
		}
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2026-02-09 09:26  TH911  阅读(4)  评论(0)    收藏  举报