zoukankan      html  css  js  c++  java
  • 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; //emmm.....我也不知道为啥要减,知道的请@我qwq
                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;
    }
     
  • 相关阅读:
    HeidiSQL 导入Excel数据
    两片74门实现的双边沿D触发器
    java多线程
    java集合框架
    java异常处理
    java基础学习5
    java基础学习4
    Java基础学习3
    Java基础学习2
    LeetCode 184场周赛
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9688566.html
Copyright © 2011-2022 走看看