版权声明:小蒟蒻的博客转载也请注明出处哦 https://blog.csdn.net/qq_42835823/article/details/86656499
初步认识:处理trie树上的异或(xor)问题
bzoj3261 最大异或和
注意:
- 记录的是经过这个点的次数
- 表示查询区间内有这样的一个数
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5,inf=2e9,M=14400005;
int sum[M],son[M][2],rt[M],tot=0;
void build(int x,int &y,int v,int d){
sum[y=++tot]=sum[x]+1;//走过一遍加一
if(d<0)return;
int p=(v>>d)&1;
son[y][p^1]=son[x][p^1];
build(son[x][p],son[y][p],v,d-1);
}
int query(int x,int y,int v,int d){
if(d<0)return 0;
int p=(v>>d)&1;int tmp=sum[son[y][p^1]]-sum[son[x][p^1]];//查询区间内是否有这样的一个数
if(tmp>0)return (1<<d)+query(son[x][p^1],son[y][p^1],v,d-1);
else return query(son[x][p],son[y][p],v,d-1);
}
int n,m,all;
int main(){
scanf("%d%d",&n,&m);
build(rt[0],rt[1],0,24);
n++;
for(int i=2;i<=n;i++){
int x;
scanf("%d",&x);
all^=x;/////////////
build(rt[i-1],rt[i],all,24);
}
char s[5];
while(m--){
scanf("%s",s+1);
if(s[1]=='A'){
int x;
scanf("%d",&x);
all^=x;
build(rt[n],rt[n+1],all,24);
n++;
}
else{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",query(rt[x-1],rt[y],k^all,24));//sum[n] xor sum[p - 1] xor x
}
}
return 0;
}
loj6144 可持久化数据结构
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5,M=2050100;
int n,m,a[N],sand=0x7fffffff,sor=0,same[40],xortag=0,opt[40],rt[N];
int son[M][2],siz[M],tot;
void insert(int x,int y,int v){
for(int i=30;~i;i--){
bool f=same[i]?0:((v>>i)&1);
siz[y]=siz[x]+1;
son[y][f^1]=son[x][f^1];
y=son[y][f]=++tot;
x=son[x][f];
}
siz[y]=siz[x]+1;
}
void build(){
memset(siz,0,sizeof(siz));
memset(son,0,sizeof(son));
memset(rt,0,sizeof(rt));
rt[0]=tot=1;
insert(0,rt[0],0);
for(int i=1;i<=n;i++){
rt[i]=++tot;
insert(rt[i-1],rt[i],a[i]);
}
}
int query(int l,int r,int k){
int ans=0;
for(int i=30;~i;i--){
if(same[i]){
ans+=opt[i]<<i;
l=son[l][0];
r=son[r][0];
continue;
}
bool f=xortag&(1<<i);
int sum=siz[son[r][f]]-siz[son[l][f]];
if(sum>=k){
l=son[l][f];
r=son[r][f];
}
else{
k-=sum;
ans+=1<<i;
l=son[l][f^1];
r=son[r][f^1];
}
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sand&=a[i];
sor|=a[i];
}
for(int i=0;i<=30;i++)
same[i]=((sand>>i)&1)==((sor>>i)&1);//
build();
char s[10];int x;
while(m--){
scanf("%s",s+1);
if(s[1]=='X'){
scanf("%d",&x);
xortag^=x;//记录,查询时再修改
for(int i=0;i<=30;i++)
if(same[i]&&(x&(1<<i)))opt[i]^=1;//
}
if(s[2]=='n'){
scanf("%d",&x);
int flag=0;
for(int i=0;i<=30;i++)
if(!(x&(1<<i)))
if(same[i])opt[i]=0;
else{
flag=1;
opt[i]=0;
same[i]=1;//
}
if(flag)build();//重构
}
if(s[1]=='O'){
scanf("%d",&x);
int flag=0;
for(int i=0;i<=30;i++)
if(x&(1<<i))
if(same[i])opt[i]=1;
else{
flag=1;
opt[i]=1;
same[i]=1;
}
if(flag)build();
}
if(s[2]=='s'){
int l,r;
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",query(rt[l-1],rt[r],x));
}
}
return 0;
}