zoukankan      html  css  js  c++  java
  • 浅谈主席树

    距离CSP2019只有不到二十天了……就简单说说,然后贴个代码吧

    可持久化线段树,又名主席树(因为提出这个数据结构的人叫hjt)

    可持久化,即为可以追溯某个历史版本

    模板

    你需要维护这样的一个长度为 N 的数组,支持如下几种操作

    1. 在某个历史版本上修改某一个位置上的值

    2. 访问某个历史版本上的某一位置的值

    此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)

    详见代码和注释

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define mid (l+r>>1)
    #define maxn 1000005
    using namespace std;
    
    inline int read()
    {
        int f=1,x=0;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n,m,cnt;
    int a[maxn],t[maxn];//t:每颗线段树的编号
    int lc[maxn<<5],rc[maxn<<5],tre[maxn<<5];//lc:左儿子  rc:右儿子  tre:结点权值(需要注意的是,主席树的左右儿子不能直接用乘2和cheng2加1求出,必须存储)(注意2:主席树一般开20倍空间以上)
    
    int build(int pre,int l,int r)//建树
    {
        int rt=++cnt;
        if(l==r)
        {
            tre[rt]=a[l];
            return rt;
        }
        lc[rt]=build(lc[rt],l,mid);
        rc[rt]=build(rc[rt],mid+1,r);
        return rt;
    }
    
    int update(int pre,int l,int r,int p,int x)//单点修改
    {
        int rt=++cnt;
        lc[rt]=lc[pre],rc[rt]=rc[pre],tre[rt]=tre[pre];//当前版本继承历史版本的信息
        if(l==r)
        {
            tre[rt]=x;
            return rt;
        }
        if(p<=mid) lc[rt]=update(lc[rt],l,mid,p,x);//创建新的版本
        else rc[rt]=update(rc[rt],mid+1,r,p,x);
        return rt;
    }
    
    int query(int pre,int l,int r,int p)//单点查询
    {
        if(l==r)
        {
            return tre[pre];
        }
        if(p<=mid) return query(lc[pre],l,mid,p);
        else return query(rc[pre],mid+1,r,p);
    }
    
    int main()
    {
        int i;
        int k,x,y,z;
        n=read(); m=read();
        for(i=1;i<=n;i++) a[i]=read();
        
        t[0]=build(0,1,n);//建立最开始的版本
        for(i=1;i<=m;i++)
        {
            x=read(); k=read();
            if(k==1)
            {
                y=read(); z=read();
                t[i]=update(t[x],1,n,y,z);
            }
            if(k==2)
            {
                y=read();
                printf("%d
    ",query(t[x],1,n,y));
                t[i]=t[x];//询问也要新建状态(详见题目)
            }
        }
        return 0;
    }

    CSP2019 RP++!

  • 相关阅读:
    致 CODING 用户的元宵问候
    持续集成之理论篇
    基于 CODING 的 Spring Boot 持续集成项目
    使用 CODING 进行 Hexo 项目的持续集成
    使用 CODING 进行 Spring Boot 项目的集成
    三种前端模块化规范
    XSS和CSRF
    小问题填坑,关于obj.x和obj["x"]
    说一个闭包在实际开发中的应用
    关于return的分号自动插入问题
  • 原文地址:https://www.cnblogs.com/llllllpppppp/p/11743635.html
Copyright © 2011-2022 走看看