bzoj3261 最大异或和
Description
给定一个非负整数序列 {a},初始长度为 N。
有M个操作,有以下两种操作类型:
1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:
a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出最大是多少。
Input
第一行包含两个整数 N ,M,含义如问题描述所示。
第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
Output
假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。
Sample Input
5 5
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
对于测试点 1-2,N,M<=5 。
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
对于测试点 1-2,N,M<=5 。
对于测试点 3-7,N,M<=80000 。
对于测试点 8-10,N,M<=300000 。
其中测试点 1, 3, 5, 7, 9保证没有修改操作。
对于 100% 的数据, 0<=a[i]<=10^7。
Sample Output
4
5
6
5
6
HINT
对于100%的数据,0<=a[i]<=10^7。
正解:可持久化trie树。
很高深的样子,其实就是可持久化线段树。。
跟可持久化线段树一样的构造方法,最高位为根,两个儿子分别表示下一位的二进制是0和1。每次插入,就直接从第n个位置蒯过来。用b[i]表示a[1]-a[i]的异或和,b[i]在树上的一条链就加1。查询的时候,对于l和r,只要查询b[p-1]^b[n]^x的最大值就行。那么我们可以查询l-1到r-1的区间。如果当前位上的儿子存在与b[n]^x异或起来等于1的位,就跳到这个儿子上,否则跳到另一个儿子上,总之就是个贪心的思想吧,稍微想想就通了。然后这题空间真的太鬼了。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define il inline 16 #define RG register 17 #define ll long long 18 19 using namespace std; 20 21 int ch[2][15000010],sum[15000010],rt[15000010],a[600010],n,m,sz; 22 char s[5]; 23 24 il int gi(){ 25 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 26 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 27 } 28 29 il void insert(RG int x,RG int &rt,RG int v){ 30 rt=++sz; RG int y=rt,t; 31 for (RG int i=23;i>=0;--i){ 32 sum[y]=sum[x]+1,ch[0][y]=ch[0][x],ch[1][y]=ch[1][x]; 33 t=(v&(1<<i))>>i,ch[t][y]=++sz,x=ch[t][x],y=ch[t][y]; 34 } 35 sum[y]=sum[x]+1; return; 36 } 37 38 il int query(RG int x,RG int y,RG int v){ 39 RG int res=0,t; 40 for (RG int i=23;i>=0;--i){ 41 t=(v&(1<<i))>>i; 42 if (sum[ch[t^1][y]]-sum[ch[t^1][x]]) res+=(1<<i),x=ch[t^1][x],y=ch[t^1][y]; 43 else x=ch[t][x],y=ch[t][y]; 44 } 45 return res; 46 } 47 48 il void work(){ 49 n=gi()+1,m=gi(); RG int l,r,x; insert(rt[0],rt[1],0); 50 for (RG int i=2;i<=n;++i) a[i]=gi()^a[i-1],insert(rt[i-1],rt[i],a[i]); 51 for (RG int i=1;i<=m;++i){ 52 scanf("%s",s); 53 if (s[0]=='A') n++,a[n]=gi()^a[n-1],insert(rt[n-1],rt[n],a[n]); 54 else{ l=gi(),r=gi(),x=gi(); printf("%d\n",query(rt[l-1],rt[r],x^a[n])); } 55 } 56 return; 57 } 58 59 int main(){ 60 work(); 61 return 0; 62 }