[BZOJ3261]最大异或和
题目大意:
给定一个长度为$n(n\leq3\times10^5)$的数列$A(A_i\leq10^7)$,有$m(m\leq3\times10^5)$个操作,操作有2种:
1.在A的末尾加入一个数$x$;
2.给定$l,r,x$,找到$l\le p\le r$的$p$使得从$A_p$开始的后缀异或最大,求出这个最大值。
思路:
令$S$表示$A$的前缀异或和,则$\oplus_{i=p}^nA_i=S_{p-1}\oplus S_n$。因此可以以$S$建立可持久化字典树,在对应区间询问与$S_n\oplus x$异或的最大值。
1 #include<cstdio> 2 #include<cctype> 3 inline int getint() { 4 register char ch; 5 while(!isdigit(ch=getchar())); 6 register int x=ch^'0'; 7 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 8 return x; 9 } 10 inline char getalpha() { 11 register char ch; 12 while(!isalpha(ch=getchar())); 13 return ch; 14 } 15 const int N=6e5+1,logA=24; 16 class PresistentTrie { 17 private: 18 int val[N*logA],ch[N*logA][2]; 19 int sz,new_node(const int &p) { 20 val[++sz]=val[p]; 21 ch[sz][0]=ch[p][0]; 22 ch[sz][1]=ch[p][1]; 23 return sz; 24 } 25 public: 26 int root[N]; 27 void insert(int &p,const int &x,const int &d=logA-1) { 28 val[p=new_node(p)]++; 29 if(d==-1) return; 30 const bool b=x>>d&1; 31 insert(ch[p][b],x,d-1); 32 } 33 int query(const int &p,const int &q,const int &x,const int &d=logA-1) const { 34 if(d==-1) return 0; 35 const bool b=x>>d&1; 36 if(val[ch[p][!b]]-val[ch[q][!b]]) return query(ch[p][!b],ch[q][!b],x,d-1)|(1<<d); 37 return query(ch[p][b],ch[q][b],x,d-1); 38 } 39 }; 40 PresistentTrie t; 41 int main() { 42 int n=getint(),m=getint(),last=0; 43 t.insert(t.root[1]=t.root[0],0); 44 for(register int i=1;i<=n;i++) { 45 t.insert(t.root[i+1]=t.root[i],last^=getint()); 46 } 47 for(register int i=1;i<=m;i++) { 48 const char opt=getalpha(); 49 if(opt=='A') { 50 n++; 51 t.insert(t.root[n+1]=t.root[n],last^=getint()); 52 } 53 if(opt=='Q') { 54 const int l=getint(),r=getint(); 55 printf("%d\n",t.query(t.root[r],t.root[l-1],last^getint())); 56 } 57 } 58 return 0; 59 }