BZOJ 3261 最大异或和
题解:
答案 x^s[n]^s[p-1]
s是前缀异或
可持久化Trie树
按照二进制把数加进去
覆盖的路径权值+1
然后贪心找
用权值的差判断有没有这一位
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int u=31; const int maxn=600009; int n,m; int s[maxn]={0}; int nn=0; int root[maxn]={0}; int ch[maxn*31][2]={0},d[maxn*31]={0}; void Inser(int &now,int pre,int bi,int x){ now=++nn; ch[now][0]=ch[pre][0]; ch[now][1]=ch[pre][1]; d[now]=d[pre]+1; if(bi==1)return; if(x&(1<<(bi-2)))Inser(ch[now][1],ch[pre][1],bi-1,x); else Inser(ch[now][0],ch[pre][0],bi-1,x); } int Querymax(int now,int pre,int bi,int x){ if(bi==1)return 0; if(x&(1<<(bi-2))){ if(d[ch[now][0]]-d[ch[pre][0]]==0){ return Querymax(ch[now][1],ch[pre][1],bi-1,x); }else{ return (1<<(bi-2))+Querymax(ch[now][0],ch[pre][0],bi-1,x); } }else{ if(d[ch[now][1]]-d[ch[pre][1]]==0){ return Querymax(ch[now][0],ch[pre][0],bi-1,x); }else{ return (1<<(bi-2))+Querymax(ch[now][1],ch[pre][1],bi-1,x); } } } int main(){ scanf("%d%d",&n,&m); root[0]=++nn; for(int i=1;i<=n;++i){ int x;scanf("%d",&x); s[i]=s[i-1]^x; Inser(root[i],root[i-1],u,s[i]); } while(m--){ char opty=getchar(); while((opty!='A')&&(opty!='Q'))opty=getchar(); int x,y,z; if(opty=='A'){ scanf("%d",&x); ++n;s[n]=s[n-1]^x; Inser(root[n],root[n-1],u,s[n]); }else{ scanf("%d%d%d",&x,&y,&z); if(x==1){ int tm=z^s[n]; printf("%d\n",max(tm,Querymax(root[y-1],root[0],u,z^s[n]))); }else{ printf("%d\n",Querymax(root[y-1],root[x-2],u,z^s[n])); } } } return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!