P4735 最大异或和

Posted kafuuchino

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4735 最大异或和相关的知识,希望对你有一定的参考价值。

可持久化Trie
 
据n^n=0,我们可以把问题转化为前缀异或和(设为s[i]),也就是求 s[n]^s[p] 的最大值
 
显然,这是经典的Trie上贪心问题。但是询问次数过多,我们总不能每次都建一棵完整的树。
注意到,对于每次询问我们所需的Trie都只有很小的不同。
于是我们就可以用可持久化Trie,原理类似主席树。
 
(不开O2只有90pts......)
 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,cnt,ch[16800002][2],sum[16800002],rt[600002],s[600002];
inline void update(int o,int pre,int d,int x){ //插入操作:我们仅新建一条链,其他部分与老版本共用
    if(d<0) return ;
    int to=(x>>d)&1;
    ch[o][!to]=ch[pre][!to];  //接到老版本上
    sum[ch[o][to]=++cnt]=sum[ch[pre][to]]+1; //统计个数
    update(ch[o][to],ch[pre][to],d-1,x); 
}
inline int query(int o,int pre,int d,int x){ //查询操作,与主席树相似
    if(d<0) return 0;
    int to=(x>>d)&1;
    if(sum[ch[o][!to]]>sum[ch[pre][!to]]) return (1<<d)+query(ch[o][!to],ch[pre][!to],d-1,x);  //在区间内可以走
    else return query(ch[o][to],ch[pre][to],d-1,x);
}
int main(){
    scanf("%d%d",&n,&m); int q1,q2,q3; char opt[3];
    update(rt[0]=++cnt,0,25,0); //预建一棵全0树
    for(int i=1;i<=n;++i) scanf("%d",&q1),s[i]=s[i-1]^q1,update(rt[i]=++cnt,rt[i-1],25,s[i]); 
    for(int i=1;i<=m;++i){
        scanf("%s",opt); scanf("%d",&q1);
        if(opt[0]==A) ++n,s[n]=s[n-1]^q1,update(rt[n]=++cnt,rt[n-1],25,s[n]);
        else{
            scanf("%d%d",&q2,&q3);
            --q1; --q2;
            if(q1==0) printf("%d
",query(rt[q2],0,25,q3^s[n]));
            else printf("%d
",query(rt[q2],rt[q1-1],25,q3^s[n]));
        }
    }return 0;
}

 

 

以上是关于P4735 最大异或和的主要内容,如果未能解决你的问题,请参考以下文章

P4735 最大异或和

洛谷P4735 最大异或和

P4735 最大异或和

[P4735] 最大异或和 - 可持久化Trie

[Luogu P4735]最大异或和(可持久化Trie)

可持久化Trie树