【模板】可持久化trie(luoguP4735)

题目链接:https://www.luogu.com.cn/problem/P4735

题意:n次操作,每次操作要么在序列后面加入一个数, 要么给定某个值x,以及区间 l r ,让你选择 一个 p ( l<= p <= r ) ,使得其异或前缀值异或x 的值最大。

trie树的模板题啦。

其实就好像普通主席树那样,插入值和查询都差不多的,只不过这了是trie树(为了那道线段树分治,火星商店,特地来学的可持久化trie树)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 6e5+9;
 4 struct Trie{
 5     int cnt;
 6     int tr[N*30][2],sum[N*30];
 7     int insert(int las,int val){
 8         int tem , now;
 9         tem = now = ++cnt;
10         for(int i = 23;i>=0;--i){
11             tr[now][0] = tr[las][0];
12             tr[now][1] = tr[las][1];
13             sum[now] = sum[las] + 1;
14             bool t = (1<<i) & val;
15             las = tr[las][t];
16             tr[now][t] = ++cnt;
17             now = tr[now][t];
18         }
19         sum[now] = sum[las] + 1;
20         return tem;
21     }
22     int query(int l,int r,int val){
23         int tem = 0;
24         for(int i = 23;i>=0;--i){
25             bool t = (1<<i) & val;
26             if( sum[ tr[r][t^1] ] - sum[ tr[l][t^1] ] ){
27                 tem |= (1<<i);
28                 r = tr[r][t^1];
29                 l = tr[l][t^1];
30             }
31             else r = tr[r][t] , l = tr[l][t];
32         }
33         return tem;
34     }
35 }trie;
36 int a[N],b[N],root[N];
37 char s[10];
38 int main(){
39     int n,m; scanf("%d %d",&n,&m);
40     ++n;
41     for(int i = 2;i<=n;++i) scanf("%d",a+i);
42     for(int i = 1;i<=n;++i) b[i] = b[i-1] ^ a[i];
43     for(int i = 1;i<=n;++i) root[i] = trie.insert(root[i-1],b[i]);
44     for(int i = 1;i<=m;++i){
45         scanf("%s",s);
46         if( s[0] == 'A'){
47             ++n;
48             scanf("%d",a+n);
49             b[n] = b[n-1] ^ a[n];
50             root[n] = trie.insert(root[n-1],b[n]);
51         }
52         else{
53             int l,r,x; scanf("%d %d %d",&l,&r,&x);
54             printf("%d\n",trie.query(root[l-1],root[r],b[n]^x));
55         }
56     }
57     return 0;
58 }
View Code

 

posted @ 2020-04-03 23:35  小布鞋  阅读(85)  评论(0编辑  收藏