题目:
题解:
本来喵喵喵还在好好写分块,结果突然发现要求最大异或和?没办法又是一个坑,顺道补了吧
牵扯到xor的东西要有意识地想到用trie树。
既然都是可持久化的就跟主席树的感觉差不多吧
设
sum[i]
s
u
m
[
i
]
表示
1...i
1...
i
的异或和,那么题目要求的即为
sum[i]
s
u
m
[
i
]
^
sum[n]
s
u
m
[
n
]
^
x
x
,。由于
sum[n]
s
u
m
[
n
]
和
x
x
都是定值,那么我们需要维护的就是。
将
sum[i]
s
u
m
[
i
]
转化为二进制数,然后建立可持久化trie树。利用前缀和相减的思想,对于每一个询问只需要根据
sum[n]
s
u
m
[
n
]
^
x
x
的每一个二进制位在trie树上对应寻找就可以了,尽量让异或值为1,实在不行就为0,贪心选取,为什么这样是对的呢?因为后面的位全是1也比高位的1小。
因为还会出现^
x
x
这种答案,所以要特别判断一下
代码:
#include <cstdio>
#include <iostream>
using namespace std;
const int sz=24;
const int N=600005;
int sum[N*30],ch[N*30][2],root[N],size,ans;
void insert(int &now,int x,int dep)
{
sum[++size]=sum[now]+1; ch[size][0]=ch[now][0]; ch[size][1]=ch[now][1];
now=size;
if (dep==-1) return;
int k=(x>>dep)&1;
if (!k) insert(ch[now][0],x,dep-1);
else insert(ch[now][1],x,dep-1);
}
void qurry(int l,int r,int x,int dep)
{
if (dep==-1) return;
int k=(x>>dep)&1;
if (sum[ch[r][k^1]]-sum[ch[l][k^1]]>0)
{
ans+=(1<<dep);
qurry(ch[l][k^1],ch[r][k^1],x,dep-1);
}else qurry(ch[l][k],ch[r][k],x,dep-1);
}
int main()
{
int n,m,x,tot=0,l,r;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&x),tot^=x;
root[i]=root[i-1];
insert(root[i],tot,sz);
}
while (m--)
{
char st[5];scanf("%s",st);
if (st[0]=='A')
{
scanf("%d",&x),tot^=x;
n++;root[n]=root[n-1];
insert(root[n],tot,sz);
}
else
{
scanf("%d%d%d",&l,&r,&x);
l--;r--;ans=0;
qurry(root[l-1],root[r],tot^x,sz);
if (l==0) ans=max(ans,tot^x);
printf("%d\n",ans);
}
}
}