最大异或和
最大异或和
https://ac.nowcoder.com/acm/problem/51120
题意
给你一个序列,让你进行
次操作。操作有如下两种:1.在序列末尾添加一个数
。2.求以
到
内的任意位置
为起始,以
为结尾,是的这个子序列异或和最大。
分析
可以看出这是一个可持久化Tire树,首先利用前缀和转化问题,将查询操作转化为求。如果查询没有区间限制,那么就是一个Tire树就可以。但有了区间限制就无法直接用Tire树求解。考虑用可持久化,每次询问区间
时即为相当于用第
个版本的树-第
个版本的树得到
区间的树。
代码
#include<bits/stdc++.h>
#define ll long long
const int N=1e8+5,INF=0x3f3f3f3f,mod=998244353;
using namespace std;
int n,m;
int root[N],son[N][2],tot,rtn,sum[N];
int base[32];
char opt[5];
inline int read()
{
register int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
int qpow(int a,int b)
{
int ans=1;
while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}
return ans;
}
void add(int x)
{
root[++rtn]=tot+1;
int last=root[rtn-1];
for(int i=23;~i; i--)
{
sum[++tot]=sum[last]+1;
bool b=x&base[i];
son[tot][b]=tot+1,son[tot][!b]=son[last][!b];
last=son[last][b];
}
sum[++tot]=sum[last]+1;
}
int query(int lt,int rt,int x)
{
if(lt>rt) return 0;
lt=root[lt-1];
rt=root[rt];
int ans=0;
for(int i=23;~i; i--)
{
bool b=x&base[i];
if(sum[son[rt][!b]]-sum[son[lt][!b]])
ans+=base[i],lt=son[lt][!b],rt=son[rt][!b];
else
lt=son[lt][b],rt=son[rt][b];
}
return ans;
}
int main()
{
n=read();m=read();
base[0]=1;
for(int i=1;i<=23;i++) base[i]=base[i-1]<<1;
add(0);
int now=0;
for(int i=1;i<=n;i++)
{
int x=read();
add(now^=x);
}
for(int i=1;i<=m;i++)
{
scanf("%s",opt);
if(opt[0]=='A')
{
int x=read();
add(now^=x);
}
else
{
int l=read(),r=read(),x=read();
printf("%d\n",query(l,r,now^x));
}
}
return 0;
}

海康威视公司福利 1235人发布