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

本文介绍了一种使用段式树状数组处理历史版本数据的方法,支持在历史版本上修改数组值及访问特定版本的值。通过递归构建和更新树节点,实现了高效的版本管理和查询操作。

题目:https://www.luogu.org/problem/P3919

维护这样的一个长度为 N 的数组,支持如下几种操作
在某个历史版本上修改某一个位置上的值
访问某个历史版本上的某一位置的值
此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)
1≤N,M≤10610^6106

code:

#include<bits/stdc++.h>
using namespace std;
#define mid ((l + r) >> 1)
#define Lson l, mid
#define Rson mid + 1, r
const int MAXN = 1e6 + 9;
int n, m, k;
int root[MAXN];
struct Tree
{
    int l, r, num;
}tree[MAXN * 32];
int build(int l, int r)
{
    int now = ++k;

    if(l == r)
    {
         scanf("%d", &tree[now].num);
         return now;
    }

    tree[now].l = build(Lson);
    tree[now].r = build(Rson);
    return now;
}
int upDate(int pre, int l, int r, int pos, int val)
{
    int now = ++k;

    if(l == r)
    {
        tree[now].num = val;
        return now;
    }
    tree[now].l = tree[pre].l;
    tree[now].r = tree[pre].r;
    if(l < r)
    {
        if(pos <= mid)
            tree[now].l = upDate(tree[pre].l, Lson, pos, val);
        else
            tree[now].r = upDate(tree[pre].r, Rson, pos, val);
    }
    return now;

}
int query(int pre, int l, int r, int pos)
{
    int now = pre;
    if(l == r)
    {
        return tree[now].num;
    }
    if(pos <= mid)
        return query(tree[now].l, Lson, pos);
    else
        return query(tree[now].r, Rson, pos);
}
int main()
{
    scanf("%d %d", &n, &m);
    root[0] = build(1, n);
    int vir, op, pos, val;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d %d", &vir, &op, &pos);
        if(op == 1)
        {
            scanf("%d", &val);
            root[i] = upDate(root[vir], 1, n, pos, val);
        }
        else
        {
            root[i] = root[vir];
            printf("%d\n",query(root[vir], 1, n, pos));
        }

    }
    return 0;
}

洛谷平台上并没有特别典型的专门针对可持久化可并堆的模板题,但可以通过一些数据结构和算法的综合题目来锻炼相关的实现能力。以下是一些可能有帮助的题目: #### P3835 【模板可持久化平衡树 虽然这是可持久化平衡树模板题,但在实现可持久化的思路上有一定的借鉴意义。它需要维护一个可重整数集合,支持插入、删除、查询排名、查询排名对应的数、求前驱和后继等操作,且每次操作基于某一历史版本并生成新的版本。 ```python # 简单示例代码框架,非完整实现 class Node: def __init__(self): self.left = None self.right = None self.val = 0 def build(l, r): node = Node() if l == r: return node mid = (l + r) // 2 node.left = build(l, mid) node.right = build(mid + 1, r) return node ``` #### P3919模板可持久化线段树 1(可持久化数组) 该题涉及对数组的修改和查询操作,每次操作会产生新的版本,对于理解可持久化数据结构的版本维护有帮助。 ```python # 简单示例代码框架,非完整实现 class Node: def __init__(self): self.left = None self.right = None self.val = 0 def update(pre, l, r, pos, val): cur = Node() cur.left = pre.left cur.right = pre.right cur.val = pre.val if l == r: cur.val = val return cur mid = (l + r) // 2 if pos <= mid: cur.left = update(pre.left, l, mid, pos, val) else: cur.right = update(pre.right, mid + 1, r, pos, val) return cur ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值