• 洛谷:P3919 【模板】可持久化数组(可持久化线段树/平衡树)


    原题地址:https://www.luogu.org/problemnew/show/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];
            }
        }
    }
    
  • 相关阅读:
    Golang中用==判断是否相等
    reactnative项目运行失败的解决方法
    使用Redis实现分布式锁
    Zksnarks笔记: from programe to QAP
    [loj6696]复读机 加强版
    [loj3561]The short shank; Redemption
    [atARC135D]Add to Square
    [atARC134F]Flipping Coins
    [loj2157]避雷针
    [loj3653]抽奖机
  • 原文地址:https://www.cnblogs.com/yyy2015c01/p/8456013.html
Copyright © 2020-2023  润新知