浅谈主席树

Posted llllllpppppp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈主席树相关的知识,希望对你有一定的参考价值。

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

以上是关于浅谈主席树的主要内容,如果未能解决你的问题,请参考以下文章

可持久化专题——浅谈主席树:可持久化线段树

浅谈树状数组套主席树

可持久化线段树--主席树

主席树算法解析

[数据结构] 主席树初识(理论,代码待补)

代码源 Div1 - 108#464. 数数(主席树,区间比k小的数的个数)HDU4417