可持久化trie
可持久化trie树
https://www.luogu.org/problem/P4735
题目描述
给定一个非负整数序列{a},初始长度为N。
有M个操作,有以下两种操作类型:
-
A x
:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。 -
Q l r x
:询问操作,你需要找到一个位置p,满足l≤p≤r,使得:a[p]⊕a[p+1]⊕...⊕a[N]⊕x最大,输出最大是多少。solution
异或满足可减性,所以可以维护前缀和
添加操作就方便了
就是询问操作不太好处理
// luogu-judger-enable-o2 #include <bits/stdc++.h> using namespace std; #define maxn 600009 int rt[maxn],cnt[maxn*28]; int ch[maxn*28][2]; int qz[maxn]; int tt=1; int n,m; void ins(int a,int b,int t,int x) { if(t<0) return; int i=(x>>t)&1; ch[a][!i]=ch[b][!i]; ch[a][i]=tt++; cnt[ch[a][i]]=cnt[ch[b][i]]+1; ins(ch[a][i],ch[b][i],t-1,x); } int qu(int a,int b,int t,int x) { if(t<0) return 0; int i=(x>>t)&1; if(cnt[ch[b][!i]]>cnt[ch[a][!i]]) { return (1<<t)+qu(ch[a][!i],ch[b][!i],t-1,x); } else { return qu(ch[a][i],ch[b][i],t-1,x); } } int main(){ scanf("%d%d",&n,&m); int a,b,c,i,j; char s[5]; rt[0]=tt++; ins(rt[0],0,25,0); for(a=1;a<=n;a++) { scanf("%d",&b); qz[a]=qz[a-1]^b; rt[a]=tt++; ins(rt[a],rt[a-1],25,qz[a]); } for(a=1;a<=m;a++) { scanf("%s",s); if(s[0]=='A') { scanf("%d",&b); n++; qz[n]=qz[n-1]^b; rt[n]=tt++; ins(rt[n],rt[n-1],25,qz[n]); } else { scanf("%d%d%d",&i,&j,&b); i--;j--; if(i==0) printf("%d\n",qu(0,rt[j],25,b^qz[n])); else printf("%d\n",qu(rt[i-1],rt[j],25,b^qz[n])); } } return 0; }
还有一种非递归版的:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,trie[20000000][2],root[20000000],size[20000000],node_cnt,node;
inline int read()
{
int X(0),w(0);char ch(0);
while (!isdigit(ch))w|=ch=='-',ch=getchar();
while (isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void write(int x)
{
if (x<0) putchar('-'),x=-x;
if (x>9) write(x/10);
putchar(x%10+'0');
}
int getc()
{
char ch=getchar();
while(ch<'A'||ch>'Z')ch=getchar();
return ch=='A';
}
void insert(int x)
{
int rt=root[node_cnt];
root[++node_cnt]=++node;
for (register int i=24;i>=0;i--)
{
int ch=(x>>i)&1;
size[node]=size[rt]+1;
trie[node][ch]=node+1;
trie[node][!ch]=trie[rt][!ch];
rt=trie[rt][ch];
node++;
}
size[node]=size[rt]+1;
}
void query(int l,int r,int x)
{
int lc=root[l],rc=root[r],ans=0;
for (register int i=24;i>=0;i--)
{
int ch=(x>>i)&1;
if (size[trie[rc][!ch]]-size[trie[lc][!ch]]>0)
lc=trie[lc][!ch],rc=trie[rc][!ch],ans|=1<<i;
else
lc=trie[lc][ch],rc=trie[rc][ch];
}
write(ans);
putchar(10);
}
int main()
{
n=read();m=read();
int x,sum=0;
insert(0);
for (register int i=1;i<=n;i++)
x=read(),sum^=x,insert(sum);
int l,r,z,ch;
for (register int i=1;i<=m;i++)
{
ch=getc();
if (ch==1)
z=read(),sum^=z,insert(sum);
else
l=read(),r=read(),z=read(),query(l-1,r,z^sum);
}
return 0;
}