洛谷 P3919 【模板】可持久化线段树 1(可持久化数组)

洛谷 P3919 【模板】可持久化线段树 1(可持久化数组)

洛谷传送门

题目描述

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

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

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

输入格式

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

第二行包含NN个整数,依次为初始状态下数组各位的值(依次为 a_ia**i,1 leq i leq N1≤iN)。

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

  1. 对于操作1,格式为v_i 1 {loc}_i {value}iv**i 1 loc**i value**i,即为在版本v_iv**i的基础上,将 a{{loc}_i}aloci 修改为 {value}_ivalue**i
  2. 对于操作2,格式为v_i 2 {loc}iv**i 2 loc**i,即访问版本v_iv**i中的 a{{loc}_i}aloci的值,生成一样版本的对象应为vi

输出格式

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


题解:

一道主席树的板子题,没学过的请走这边:

详解主席树

直接放代码:

#include<cstdio>
using namespace std;
const int maxn=1e6+10;
int n,m;
int a[maxn],root[maxn];
struct persistent_segment_tree
{
    int lson,rson,val;
}tree[maxn*24];
int tot,ver;
void build(int &pos,int l,int r)
{
    int mid=(l+r)>>1;
    if(!pos)
        pos=++tot;
    if(l==r)
    {
        tree[pos].val=a[l];
        return;
    }
    build(tree[pos].lson,l,mid);
    build(tree[pos].rson,mid+1,r);
    tree[pos].val=tree[tree[pos].lson].val+tree[tree[pos].rson].val;
}
int newnode(int pos)
{
    tree[++tot]=tree[pos];
    return tot;
}
int update(int pos,int l,int r,int x,int k)
{
    int mid=(l+r)>>1;
    pos=newnode(pos);
    if(l==r)
    {
        tree[pos].val=k;
        return pos;
    }
    if(x<=mid)
        tree[pos].lson=update(tree[pos].lson,l,mid,x,k);
    else
        tree[pos].rson=update(tree[pos].rson,mid+1,r,x,k);
    return pos;
}
int query(int pos,int l,int r,int x)
{
    int mid=(l+r)>>1;
    if(l==r)
        return tree[pos].val;
    if(x<=mid)
        return query(tree[pos].lson,l,mid,x);
    else
        return query(tree[pos].rson,mid+1,r,x);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(root[0],1,n);
    while(m--)
    {
        int v,opt;
        int x,k;
        scanf("%d%d",&v,&opt);
        if(opt==1)
        {
            scanf("%d%d",&x,&k);
            root[++ver]=update(root[v],1,n,x,k);
        }
        else
        {
            scanf("%d",&x);
            root[++ver]=root[v];
            printf("%d
",query(root[v],1,n,x));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13677998.html