最大异或和
最大异或和
https://ac.nowcoder.com/acm/problem/51120
分析
首先,我们将题目化简一下
由于
设Pre[]
表示异或前缀和
所以我们其实只需要维护Pre[]
即可
每次在一定的区间内查询与当前Pre[N]
异或的最大值即可
由于是区间查询,并且需要动态维护
所以我们可以使用类似于主席树的维护方式进行维护
即可持久化01Trie
树
动态进行开点
由于每次只会修改到个节点
查询的时候同样为个节点
所以总的
时间复杂度:
空间复杂度:
期望得分:100分
代码
//P4735 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define LL long long #define Cl(X,Y) memset((X),(Y),sizeof(X)) #define FOR(i,A,B) for(int i=A;i<=B;i++) #define BOR(i,A,B) for(int i=A;i>=B;i--) #define Lowbit(X) (X & (-X)) #define INF 0x3f3f3f3f #define Rson (X<<1|1) #define Lson (X<<1) using namespace std; const int MaxN=6e5+10,MaxM=100; int Child[MaxN<<6][2],Size,Cnt[MaxN<<6][2]; int Ans,Root[MaxN],u,v,w; int Total,Test,Bit[MaxM],Loc; int Num[MaxN],Pre[MaxN],Two[MaxM]={1}; char Opt[5]; inline void File() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inline void Copy(int Res,int New) { Child[Res][1]=Child[New][1]; Child[Res][0]=Child[New][0]; Cnt[Res][0]=Cnt[New][0]; Cnt[Res][1]=Cnt[New][1]; } inline int Update(int New,int Temp,int Mine) { if(Temp==-1) return 0; Bit[Temp]=((Mine>>Temp) & 1); int Res=++Size; Copy(Res,New); Cnt[Res][Bit[Temp]]++; if(Bit[Temp]) { Child[Res][1]=Update(Child[New][1],Temp-1,Mine); } else { Child[Res][0]=Update(Child[New][0],Temp-1,Mine); } return Res; } inline int Get(int Left,int Right,int Temp,int Mine) { if(Temp==-1) return 0; Bit[Temp]=((Mine>>Temp) & 1); if(Bit[Temp]) { if(Cnt[Right][0]-Cnt[Left][0]>0) { return (Two[Temp]|Get(Child[Left][0],Child[Right][0],Temp-1,Mine)); } else { return Get(Child[Left][1],Child[Right][1],Temp-1,Mine); } } else { if(Cnt[Right][1]-Cnt[Left][1]>0) { return (Two[Temp]|Get(Child[Left][1],Child[Right][1],Temp-1,Mine)); } else { return Get(Child[Left][0],Child[Right][0],Temp-1,Mine); } } } signed main() { // File(); // ios::sync_with_stdio(false); FOR(i,1,30) Two[i]=Two[i-1]*2; cin>>Total>>Test; Root[0]=Update(0,23,0); FOR(i,1,Total) { cin>>Num[i]; Pre[i]=Pre[i-1]^Num[i]; Root[i]=Update(Root[i-1],23,Pre[i]); } while(Test--) { scanf("%s",Opt+1); if(Opt[1]=='A') { cin>>u; Num[++Total]=u; Pre[Total]=Pre[Total-1]^Num[Total]; Root[Total]=Update(Root[Total-1],23,Pre[Total]); } else { scanf("%d %d %d",&u,&v,&w); if(v==1) printf("%d\n",Pre[Total]^w); else if(u!=1) printf("%d\n",Get(Root[u-2],Root[v-1],23,w^Pre[Total])); else printf("%d\n",Get(0,Root[v-1],23,w^Pre[Total])); } } // fclose(stdin); // fclose(stdout); // system("pause"); return 0; }