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 */

 

posted @ 2017-12-25 18:56  lokiii  阅读(146)  评论(0编辑  收藏  举报