zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    sed中求公共前缀
    DB9 公头母头引脚定义及连接
    J2SE基础:4.面向对象的特性一
    Android APK反编译具体解释(附图)
    wxWidgets刚開始学习的人导引(1)——前言
    使用Visual Studio 2010 创建简单的Silverlight应用程序
    MyEclipse下XFire开发Webservice实例
    实战DeviceIoControl 之中的一个:通过API訪问设备驱动程序
    素数推断算法(高效率)
    Ansi,UTF8,Unicode,ASCII编码的差别
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12253339.html
Copyright © 2011-2022 走看看