最大异或和题解

最大异或和题解

其实很简单了,
xor->分位操作
动态维护->只可能是可持久化0、1 trie 树了吧
然后每次加入新点便更新版本,
将查询\(\sum_{i=p}^{N} a[i] xor X(p \in [l,r])\),(这里的\(\sum!=+, = xor\)),
变为\((\sum_{i=1}^{N} xor X) xor \sum_{i=1}^{p-1} (p-1 \in [l-1,r-1])\)
将每个点变为前缀和选出与\(sum[N] xor x\)异或起来最大的值,在tire 树上一步一步走即可,

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7,M=6e5+7,P=27;
int n,m,t,num,cnt=1,a[M],son[M*P][2],pre[M*P],tmp[P],p,q,t1,t2,t3,rt[M];
char c[12];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void update(int x,int y,int z){
     for(int i=24;i>=0;--i) tmp[25-i]=((x>>i)&1);
     rt[z]=++cnt,p=cnt;
     for(int i=1;i<=25;++i){
         son[p][tmp[i]^1]=son[y][tmp[i]^1];
         son[p][tmp[i]]=++cnt,pre[cnt]=z;
         p=cnt,y=son[y][tmp[i]];
     }
}
int query(int l,int r,int x){
    p=rt[r],t=(a[num]^x); int ans=0;
    for(int i=24;i>=0;--i) tmp[25-i]=(!((t>>i)&1));
    for(int i=1;i<=25;++i){
        t=son[p][tmp[i]];
        if(t&&pre[t]>=l) p=son[p][tmp[i]],ans+=(1<<(25-i));
        else{
            if(son[p][tmp[i]^1]) p=son[p][tmp[i]^1];
            else return ans;
        }
    }
    return ans;
}
int main(){
    n=read(),m=read(),num=n,rt[0]=1,p=1;
    for(int i=1;i<=25;++i) son[p][0]=++cnt,p=cnt;
    for(int i=1;i<=n;++i) a[i]=read(),a[i]^=a[i-1],update(a[i],rt[i-1],i);
    for(int i=1;i<=m;++i){
        scanf("%s",c),t1=read();
        if(c[0]=='A') a[++num]=t1,a[num]^=a[num-1],update(a[num],rt[num-1],num);
        else t2=read(),t3=read(),printf("%d\n",query(t1-1,t2-1,t3));
    }
    return 0;
}
posted @ 2019-10-16 20:01  lsoi_ljk123  阅读(129)  评论(0编辑  收藏  举报