原题地址: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];
        }
    }
}

相关文章:

  • 2021-10-11
  • 2022-12-23
  • 2022-02-09
  • 2021-07-05
  • 2021-06-28
  • 2021-09-29
  • 2021-09-07
  • 2022-03-05
猜你喜欢
  • 2021-11-15
  • 2021-05-31
  • 2022-12-23
  • 2021-09-04
  • 2021-11-23
  • 2022-01-23
相关资源
相似解决方案