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 。

对于测试点 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

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 }

 

posted @ 2017-02-27 10:10  wfj_2048  阅读(655)  评论(0编辑  收藏  举报