bzoj 3261 最大异或和【可持久化trie】
因为在后面加数字又求后缀和太麻烦,所以xor[p...n]=xor[1...n]^xor[p-1...n]。
首先处理出来区间异或前缀和,对前缀和建trie树(在最前面放一棵0表示最开始的前缀和
然后就是可持久化trie的板子了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int N=600005; 6 int n,m,a[N],b[N],rt[N],cnt; 7 char c[5]; 8 struct qwe 9 { 10 int c[2],sum; 11 }t[N*25]; 12 int read() 13 { 14 int r=0; 15 char p=getchar(); 16 while(p>'9'||p<'0') 17 p=getchar(); 18 while(p>='0'&&p<='9') 19 { 20 r=r*10+p-48; 21 p=getchar(); 22 } 23 return r; 24 } 25 int add(int x,int v) 26 { 27 int tmp=++cnt,y=cnt; 28 for(int i=23;i>=0;i--) 29 { 30 t[y].c[0]=t[x].c[0]; 31 t[y].c[1]=t[x].c[1]; 32 t[y].sum=t[x].sum+1; 33 int q=(v&(1<<i))>>i; 34 x=t[x].c[q]; 35 t[y].c[q]=++cnt; 36 y=t[y].c[q]; 37 } 38 t[y].sum=t[x].sum+1; 39 return tmp; 40 } 41 int ques(int l,int r,int v) 42 { 43 int re=0; 44 for(int i=23;i>=0;i--) 45 { 46 int q=(v&(1<<i))>>i; 47 if(t[t[r].c[q^1]].sum-t[t[l].c[q^1]].sum) 48 re+=(1<<i),l=t[l].c[q^1],r=t[r].c[q^1]; 49 else 50 l=t[l].c[q],r=t[r].c[q]; 51 } 52 return re; 53 } 54 int main() 55 { 56 n=read(),m=read(); 57 n++; 58 for(int i=2;i<=n;i++) 59 a[i]=read(); 60 for(int i=1;i<=n;i++) 61 b[i]=b[i-1]^a[i]; 62 for(int i=1;i<=n;i++) 63 rt[i]=add(rt[i-1],b[i]); 64 while(m--) 65 { 66 scanf("%s",c); 67 if(c[0]=='A') 68 { 69 a[++n]=read(); 70 b[n]=b[n-1]^a[n]; 71 rt[n]=add(rt[n-1],b[n]); 72 } 73 else 74 { 75 int l=read(),r=read(),x=read(); 76 printf("%d\n",ques(rt[l-1],rt[r],b[n]^x)); 77 } 78 } 79 return 0; 80 } 81 /* 82 5 5 83 2 6 4 3 6 84 A 1 85 Q 3 5 4 86 A 4 87 Q 5 7 0 88 Q 3 6 6 89 */