• P4735 最大异或和 /【模板】可持久化Trie


    本题是可持久化0-1 trie树的题目

    做这题我相信都已经学会可持久化trie树的基本方法,所以本文不过多解释原理

    在下面代码中有很多注释,介绍了写法。

    可持久化trie树的重点就是他只在原有基础上新增了添加的内容,而保留前面的,所以用到了很多复制的操作

    01trie树当中,假如该位置为1,那么我们只需要把0引用到前一版本的0上面,这样就复制过来了,而前一版本的1还没有复制

    所以我们可以采取递归的方法不断复制下去。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    #include<cstring>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N=600010;
    const int M=N*25;
    int tr[M][2];
    int idx;
    int s[N];
    int root[N];
    int id[M];
    void insert(int u,int k,int p,int q){
        if(k<0){  //23次操作全部结束后更新该位置的编号 
            id[q]=u;
            return ;
        }
        int v=s[u]>>k&1;
        if(p){  //如果该节点存在子孩子,那么就把v^1的值引用他 
        tr[q][v^1]=tr[p][v^1];    //把前一次的复制一遍 
        }
        tr[q][v]=++idx; //给现在的值开辟新节点 
        insert(u,k-1,tr[p][v],tr[q][v]);//因为我们开辟了新节点,所以上次的有一段节点没保存,因此需要将他传递保存 
        id[q]=max(id[tr[q][0]],id[tr[q][1]]); //更新完毕后将左右节点的编号最大值存储,编号的意思是第几个前缀和 
    }
    int query(int u,int c,int l){  //u是最后一次持久化结构的root节点,c是我们要询问的值,l是边界 
        int i;
        int res=0;
        for(i=23;i>=0;i--){
            int v=c>>i&1;
            if(id[tr[u][v^1]]>=l){ //只有节点编号满足条件才能转移 
                res+=1<<i;
                u=tr[u][v^1];
            }
            else
               u=tr[u][v];
        }
        return res;
    }
    int main(){
        int i;
        int n,m;
        scanf("%d%d",&n,&m);
        root[0]=++idx;
        id[0]=-1;
        s[0]=0;
        insert(0,23,0,root[0]);
        for(i=1;i<=n;i++){
            scanf("%d",&s[i]);
            s[i]^=s[i-1];
            root[i]=++idx;
            insert(i,23,root[i-1],root[i]);
        }
        char t[2];
        for(i=1;i<=m;i++){
            scanf("%s",t);
            if(*t=='A'){
            n++;
            scanf("%d",&s[n]);
            s[n]^=s[n-1];
            root[n]=++idx;
            insert(n,23,root[n-1],root[n]);    
            }
            else{
                int l,r,x;
                scanf("%d%d%d",&l,&r,&x);
                printf("%d
    ",query(root[r-1],s[n]^x,l-1));
                
            }
            
        }
    }
    View Code
  • 相关阅读:
    用户、角色、权限管理-设计方案之权限检测
    供电绘图计算软件-新增了图库管理功能
    AutoCAD使用技巧六则
    环境影像评价系统
    AutoCAD.net: 如何实现裁剪功能Trim
    AutoCAD 命令参考手册
    arx常用的一些函数功能表
    AutoCAD.net: Curve.GetSplitCurves的用法
    AutoCAD.net:有条件选择AutoCAD实体
    电台节目管理软件
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12253339.html
Copyright © 2020-2023  润新知