码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈主席树

时间:2019-10-26 17:15:27      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:size   uil   read   etc   else   getch   空间   otto   注释   

距离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\n",query(t[x],1,n,y));
            t[i]=t[x];//询问也要新建状态(详见题目)
        }
    }
    return 0;
}

 

CSP2019 RP++!

浅谈主席树

标签:size   uil   read   etc   else   getch   空间   otto   注释   

原文地址:https://www.cnblogs.com/llllllpppppp/p/11743635.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!