BZOJ3261: 最大异或和
$n \leq 300000$的数列支持$m \leq 300000$个操作:在末端插入一个数;询问整个数列的所有后缀异或和中$[L,R]$这些后缀异或和,异或上数字$x$后的哪一个最大。数字$\leq 1e7$。
转前缀和,变成$pre_n \ \ xor \ \ pre_{p-1} \ \ xor x,L-1 \leq p \leq R-1$。在区间里找一个数能异或上某个数最大,干这事需要可持久化Trie。写过主席树的可以直接yy。
1 #include<stdio.h> 2 #include<string.h> 3 //#include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 #define LL long long 8 int qread() 9 { 10 char c; int s=0,t=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (t=-1); 11 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*t; 12 } 13 14 // 15 16 int n,m; 17 #define maxn 600011 18 int root[maxn]; 19 struct Trie 20 { 21 struct Node{int ls,rs,cnt;}a[maxn*26]; 22 int size; 23 void insert(int &x,int y,int v) 24 { 25 int w=x=++size; a[w].cnt=1; 26 for (int i=25;~i;i--) 27 { 28 int u=(v>>i)&1; 29 a[w].ls=a[y].ls; a[w].rs=a[y].rs; 30 if (u) {a[w].rs=++size; w=size; y=a[y].rs;} 31 else {a[w].ls=++size; w=size; y=a[y].ls;} 32 a[w].cnt=a[y].cnt+1; 33 } 34 } 35 int query(int x,int y,int v) 36 { 37 int ans=0; 38 for (int i=25;~i;i--) 39 { 40 int u=(v>>i)&1; 41 if (u) 42 { 43 if (a[a[y].ls].cnt>a[a[x].ls].cnt) 44 { 45 ans|=(1<<i); 46 y=a[y].ls; x=a[x].ls; 47 } 48 else y=a[y].rs,x=a[x].rs; 49 } 50 else 51 { 52 if (a[a[y].rs].cnt>a[a[x].rs].cnt) 53 { 54 ans|=(1<<i); 55 y=a[y].rs; x=a[x].rs; 56 } 57 else y=a[y].ls,x=a[x].ls; 58 } 59 } 60 return ans; 61 } 62 }t; 63 64 int a[maxn]; 65 int main() 66 { 67 n=qread(); m=qread(); 68 t.insert(root[0],0,0); 69 for (int i=1,x;i<=n;i++) 70 { 71 x=qread(); a[i]=a[i-1]^x; 72 t.insert(root[i],root[i-1],a[i]); 73 } 74 75 char c; int x,y,v; 76 while (m--) 77 { 78 while ((c=getchar())!='A' && c!='Q'); 79 if (c=='A') 80 { 81 scanf("%d",&v); 82 n++; a[n]=a[n-1]^v; 83 t.insert(root[n],root[n-1],a[n]); 84 } 85 else 86 { 87 scanf("%d%d%d",&x,&y,&v); 88 printf("%d\n",t.query(x>1?root[x-2]:0,root[y-1],v^a[n])); 89 } 90 } 91 return 0; 92 }