可持久化trie
和主席树差不多的东西,一般用于求异或和最大之类的。
sum记录的是当前这一位(在二进制下)的值(0或1)在这一位之前出现过多少次。c[0]表示下一位为0,c[1]表示下一位为1。
关于第i位的取法:int q=(v&(1<<i))>>i;
新加一个数的时候就去沿着二进制的高位到低位一路加下来就行了。(但是为啥递归写是错的啊
查询[l,r]的与x的最 大 / 小 异或和时,用t[t[r].c[q / q^1]].sum-t[t[l].c[q / q^1]].sum即可获得[l,r]中下一位是否有和当前位相异 /相同的,即是否能使异或值当前位为1 / 0
大概这样,贴一下板子:
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 }