数据结构&字符串:可持久化字典树

利用可持久化Trie树实现范围内取值异或最大值

如果标题没有表达清楚意思,可以看这里的题干:

然后根据异或的性质,异或一个数两次相当于没有异或,那么我们可以维护一个异或前缀和

有了异或前缀和之后我们就可以通过前缀和的形式O(1)提取出任意的一个异或区间出来

然后就可以把题目转化成这样的形式

求max(b[p]^b[n]^x) (l-1<=p<=r-1)

这里只有b[p]是不知道的,我们提前把序列的异或前缀和预处理出来之后插入到可持久化Tire树里面,又因为b[n]和x是定值,这就又转化成上一篇博文中描述的问题了

只不过这里插入到Trie树里面的东西不是独立的,而是一个整体,我们要从这个整体异或中提取出关键的那一个结果来,由于我们的p是限定了范围的,那么这就相当于对应了一系列的前缀和

范围内的每一个结果都是可行的,因此我们凭借着贪心的时候能取最大取最大的思路,如果在当前Trie树里得不到局部最优解,就跳跃到另一颗更优的Trie树上进行就好了

可持久化的思想就是每一个版本的树的儿子之间乱跳

 1 #include<cstdio>
 2 const int maxn=600005;
 3 inline int read()
 4 {
 5     int x=0,f=1;char ch=getchar();
 6     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 7     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 8     return x*f;
 9 }
10 int n,m;
11 int a[maxn],b[maxn],bin[30],root[maxn];
12 struct Trie
13 {
14     int cnt;
15     int ch[maxn*24][2],sum[maxn*24];
16     int insert(int x,int val)
17     {
18         int tmp,y;
19         tmp=y=++cnt;
20         for(int i=23;i>=0;i--)
21         {
22             ch[y][0]=ch[x][0];
23             ch[y][1]=ch[x][1];
24             sum[y]=sum[x]+1;
25             int t=val&bin[i];t>>=i;
26             x=ch[x][t];
27             ch[y][t]=++cnt;
28             y=ch[y][t];
29         }
30         sum[y]=sum[x]+1;
31         return tmp;
32     }
33     int query(int l,int r,int val)
34     {
35         int tmp=0;
36         for(int i=23;i>=0;i--)
37         {
38             int t=val&bin[i];t>>=i;
39             if(sum[ch[r][t^1]]-sum[ch[l][t^1]])
40                 tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
41             else r=ch[r][t],l=ch[l][t];
42         }
43         return tmp;
44     }
45 }trie;
46 int main()
47 {
48     bin[0]=1;
49     for(int i=1;i<30;i++) bin[i]=bin[i-1]<<1;
50     n=read();m=read();
51     n++;
52     for(int i=2;i<=n;i++) a[i]=read();
53     for(int i=1;i<=n;i++) b[i]=b[i-1]^a[i];
54     for(int i=1;i<=n;i++)
55         root[i]=trie.insert(root[i-1],b[i]);
56     char ch[5];
57     int l,r,x;
58     while(m--)
59     {
60         scanf("%s",ch);
61         if(ch[0]=='A')
62         {
63             n++;
64             a[n]=read();b[n]=b[n-1]^a[n];
65             root[n]=trie.insert(root[n-1],b[n]);
66         }
67         else
68         {
69             l=read();r=read();x=read();
70             printf("%d
",trie.query(root[l-1],root[r],b[n]^x));
71         }
72     }
73     return 0;
74 }
原文地址:https://www.cnblogs.com/aininot260/p/9520075.html