可持久化字典树

Posted i am back

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化字典树相关的知识,希望对你有一定的参考价值。

1.在数组结尾插入一个数

2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大

首先我们可以维护前缀和 然后就是使x^sum[n]^sum[p-1]最大

x^sum[n]为定值,于是用Trie树贪心即可

考虑到l-1<=p-1<=r-1,我们不能对于每个询问都建一棵Trie树,但是我们可以对于Trie数维护前缀和,建立可持久化Trie树

每个区间[l,r]的Trie树为tree[r]-tree[l-1]

 

一般情况用于求区间内,异或值最大

 

/*
    data:2018.04.27
    author:gsw
    link:https://www.nowcoder.com/acm/contest/104/H
    account:tonygsw
*/
#define ll long long
#define IO ios::sync_with_stdio(false);

#include<iostream>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+5;

class Node{
    public:
        int cnt,ls,rs;
};
Node tr[maxn*40];
int root[maxn];int cnt;

int in(int pre,int x,int deep)
{
    int num=++cnt;
    tr[num]=tr[pre];
    tr[num].cnt=tr[pre].cnt+1;
    if(deep<0)return num;
    if(!((x>>deep)&1))tr[num].ls=in(tr[pre].ls,x,deep-1);
    else tr[num].rs=in(tr[pre].rs,x,deep-1);
    return num;
}
int query(int l,int r,int x,int deep)
{
    if(deep<0)return 0;
    if(!((x>>deep)&1))//为0 
    {
        if(tr[tr[r].rs].cnt>tr[tr[l].rs].cnt)return (1<<deep)+query(tr[l].rs,tr[r].rs,x,deep-1);
        else return query(tr[l].ls,tr[r].ls,x,deep-1);
    }
    else
    {
        if(tr[tr[r].ls].cnt>tr[tr[l].ls].cnt)return (1<<deep)+query(tr[l].ls,tr[r].ls,x,deep-1);
        else return query(tr[l].rs,tr[r].rs,x,deep-1);
    }
}
int main()
{
    int n,x,m,b,l,r;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        root[i]=in(root[i-1],x,29);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&b,&l,&r);
        printf("%d\n",query(root[l-1],root[r],b,29));
    }
}
/*
5
1 6 4 8 7
1
3 2 4
*/ 

 

以上是关于可持久化字典树的主要内容,如果未能解决你的问题,请参考以下文章

可持久化字典树 详解

可持久化数据结构板子整理(可持久化 线段树/字典树/可并堆)

可持久化字典树

可持久化字典树

hdu 4757 Tree(可持久化字典树)

bzoj3166: [Heoi2013]Alo 可持久化字典树