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


    题目背景

    UPDATE : 最后一个点时间空间已经放大

    标题即题意

    有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集)

    题目描述

    如题,你需要维护这样的一个长度为 NN 的数组,支持如下几种操作

    1. 在某个历史版本上修改某一个位置上的值

    2. 访问某个历史版本上的某一位置的值

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

    输入格式

    输入的第一行包含两个正整数 N, MN,M, 分别表示数组的长度和操作的个数。

    第二行包含NN个整数,依次为初始状态下数组各位的值(依次为 a_iai1 leq i leq N1iN)。

    接下来MM行每行包含3或4个整数,代表两种操作之一(ii为基于的历史版本号):

    1. 对于操作1,格式为v_i 1 {loc}_i {value}_ivi 1 loci valuei,即为在版本v_ivi的基础上,将 a_{{loc}_i}aloci 修改为 {value}_ivaluei

    2. 对于操作2,格式为v_i 2 {loc}_ivi 2 loci,即访问版本v_ivi中的 a_{{loc}_i}aloci的值,生成一样版本的对象应为vi

    输出格式

    输出包含若干行,依次为每个操作2的结果。

    输入输出样例

    输入 #1
    5 10
    59 46 14 87 41
    0 2 1
    0 1 1 14
    0 1 1 57
    0 1 1 88
    4 2 4
    0 2 5
    0 2 4
    4 2 1
    2 2 2
    1 1 5 91
    输出 #1
    59
    87
    41
    87
    88
    46



    可持久化线段树
    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e6+10;
    int  t[N<<5],ncnt,T[N<<5],lson[N<<5],rson[N<<5];
    
    void up(int x,int v,int l,int r,int pre,int &pos)
    {
        pos=++ncnt;
        lson[pos]=lson[pre];rson[pos]=rson[pre];
        if(l==r){t[pos]=v;return ;}
        int m=(l+r)>>1;
        if(x<=m)up(x,v,l,m,lson[pre],lson[pos]);
        else up(x,v,m+1,r,rson[pre],rson[pos]);
    }
    int qsum(int x,int l,int r,int pos)
    {
        if(l==r)return t[pos];
        int m=l+r>>1;
        if(x<=m) return qsum(x,l,m,lson[pos]);
        else return qsum(x,m+1,r,rson[pos]);
    }
    int a,b,c,d,x;
    int main()
    {
        int n,m;scanf("%d%d",&n,&m);
        rep(i,1,n)
        {
           scanf("%d",&x);up(i,x,1,n,T[0],T[0]);
        }
        rep(i,1,m)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b==1)
            {
                scanf("%d",&d);
                up(c,d,1,n,T[a],T[i]);
            }
            else
            {
                T[i]=T[a];//lson[T[i]]=lson[T[a]];rson[T[i]]=rson[T[a]];t[T[i]]=t[T[a]];
                printf("%d
    ",qsum(c,1,n,T[a]));
            }
        }
        return 0;
    }
    View Code



  • 相关阅读:
    数据结构 零散4(数组)
    数据结构 零散3(链表)
    数据结构 零散2(哈希表)
    数据结构 零散1(栈)
    javaweb2 URL(查找的过程)
    javaWeb1 tomcat
    vim正则表达式的替换变量
    vi搜索统计个数
    Openwrt修改默认IP,主机名,密码
    vi里面对列排序
  • 原文地址:https://www.cnblogs.com/bxd123/p/11289965.html
Copyright © 2020-2023  润新知