[bzoj3261]最大异或和[可持久化trie树]
因为要求异或和最大,所以可以考虑从高位开始,向低位枚举尽可能接近~x的值,所以以二进制位为关键字,建立可持久化trie树,根据异或和的性质,XOR_SUM{i,j}=XOR_SUM{1,j} xor XOR_SUM{1,i-1},所以查询问题也可以解决了。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 struct TRIE 12 { 13 int son[2],val; 14 }trie[25000000]; 15 16 int n,m,tot,Sum[610000]; 17 int root[610000],a[610000]; 18 19 void Insert(const int root_l,int& root_r,const int d,const int step) 20 { 21 trie[root_r=++tot]=trie[root_l]; 22 trie[root_r].val++; 23 if(step<0)return ; 24 int p=(d>>step)&1; 25 Insert(trie[root_l].son[p],trie[root_r].son[p],d,step-1); 26 return ; 27 } 28 29 int Query(const int d,const int root_l,const int root_r,const int step) 30 { 31 if(step<0)return 0; 32 int p=(d>>step)&1; 33 if(trie[trie[root_r].son[p^1]].val-trie[trie[root_l].son[p^1]].val) 34 return (1<<step)+Query(d,trie[root_l].son[p^1],trie[root_r].son[p^1],step-1); 35 return Query(d,trie[root_l].son[p],trie[root_r].son[p],step-1); 36 } 37 38 int main() 39 { 40 int i,x,l,r; 41 char op[10]; 42 43 scanf("%d%d",&n,&m); 44 n++; 45 for(i=2;i<=n;++i)scanf("%d",&a[i]); 46 for(i=1;i<=n;++i)Sum[i]=Sum[i-1]^a[i]; 47 for(i=1;i<=n;++i)Insert(root[i-1],root[i],Sum[i],23); 48 49 for(i=1;i<=m;++i) 50 { 51 scanf("%s",op); 52 if(op[0]=='A') 53 { 54 n++; 55 scanf("%d",&a[n]); 56 Sum[n]=Sum[n-1]^a[n]; 57 Insert(root[n-1],root[n],Sum[n],23); 58 } 59 else 60 { 61 scanf("%d%d%d",&l,&r,&x); 62 printf("%d\n",Query(Sum[n]^x,root[l-1],root[r],23)); 63 } 64 } 65 66 return 0; 67 }