• 浅谈主席树


    距离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++!

  • 相关阅读:
    sqlite数据库的char,varchar,text,nchar,nvarchar,ntext的区别(转)
    DELPHI XE5-8 弹出列表框供选择
    delphi弹出选择对话框选择目录|SelectDirectory 函数(转)
    php 与java安卓客户端的查询交互
    sql查询语句的拼接小技巧(高手勿喷)
    高德地图应用——与云图后台交互
    Inno Setup 通用脚本及简要说明( 一般情况够用了)
    不用SQL给打印记录编号
    DELPHI XE5/6/7 android 无线真机调试
    超级简单的例子说明JAVA PACKET CLASS 和变量之间的关系
  • 原文地址:https://www.cnblogs.com/llllllpppppp/p/11743635.html
Copyright © 2020-2023  润新知