[解题报告]P3919 模板可持久化数组(可持久化线段树/平衡树)

Posted yyy2015c01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[解题报告]P3919 模板可持久化数组(可持久化线段树/平衡树)相关的知识,希望对你有一定的参考价值。

题目简述

维护一个长度为N的数组,支持如下几种操作:

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

思路

首先感谢来自@zcysky的模板。写的非常漂亮,封装也很精致。
这题是裸题,于是直接上模板就行了。注意此题输入数据大,需要读入优化。
关于可持久化线段树的介绍与总结,之后把坑填上。


代码

    #include<bits/stdc++.h>
    const int N=1000005;
    using namespace std;
    int a[N],n,q,rt[N*20];//空间复杂度O(mlogn) 
    #define MAXB 50000000
    char buf[MAXB],*cp=buf;
    inline int read()
    {
        int f=1,x=0;
        while(*cp<'0'||*cp>'9') {
            if(*cp=='-')
                f=-1;
            cp++;
        }
        while(*cp>='0'&&*cp<='9') {
            x=x*10+*cp-'0'; 
            cp++;
        }
        return f*x;
    }
    struct Persistable_Segment_Tree {
        int lc[N*20],rc[N*20],val[N*20],cnt;
        inline void build(int &o,int l,int r){
            o=++cnt;
            if(l==r) {
                val[o]=a[l];
                return;
            }
            int mid=(l+r)>>1;
            build(lc[o],l,mid);
            build(rc[o],mid+1,r);
        }
        inline void ins(int &o,int pre,int l,int r,int q,int v){
            o=++cnt;
            lc[o]=lc[pre];
            rc[o]=rc[pre];
            val[o]=val[pre];
            if(l==r) {
                val[o]=v;
                return;
            }
            int mid=(l+r)>>1;
            if(q<=mid)
                ins(lc[o],lc[pre],l,mid,q,v);
            else 
                ins(rc[o],rc[pre],mid+1,r,q,v);
        }
        inline int query(int o,int l,int r,int q){//类似二分的查询 
            if(l==r)
                return val[o];
            int mid=(l+r)>>1;
            if(q<=mid)
                return query(lc[o],l,mid,q);
            else 
                return query(rc[o],mid+1,r,q);
        }
    }T;
    int main()
    {
        fread(buf,1,MAXB,stdin);
        n=read();
        int m=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        T.build(rt[0],1,n);
        for(int i=1;i<=m;i++){
            int pre=read(),opt=read(),x=read();
            if(opt==1) {//操作1:在版本pre的基础上将第x个数修改为v 
                int v=read();
                T.ins(rt[i],rt[pre],1,n,x,v);
            }
            if(opt==2) {//操作2:访问版本pre中第x个数的值 
                printf("%d\n",T.query(rt[pre],1,n,x));
                rt[i]=rt[pre];
            }
        }
    }

以上是关于[解题报告]P3919 模板可持久化数组(可持久化线段树/平衡树)的主要内容,如果未能解决你的问题,请参考以下文章

P3919 模板可持久化数组(可持久化线段树/平衡树)

P3919 模板可持久化数组(可持久化线段树/平衡树)

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

P3919 模板可持久化数组(可持久化线段树/平衡树)

P3919 模板可持久化数组(可持久化线段树/平衡树)(入门第一题)

解题报告:P3834 模板可持久化线段树 2(主席树)详解