栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

可持久化线段树

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

可持久化线段树

可持久化线段树就是可以查询和修改历史版本的线段树

具体实现:

  1. 我们采用动态开点的方式来建立线段树
  2. build和query操作与普通动态开点线段树如出一辙
  3. 对于修改操作,我们新增修改后的结点及其父结点,未修改过的结点直接copy过来
  4. 对于一次修改,就是一次新增祖宗的过程,也是一次添加新版本的过程

各变量含义:

t[i] - i所表示区间的权值 

lson[p] - p结点左儿子所在位置

rson[p] - p结点右儿子所在位置

v[i] - 版本i起始结点所在位置

cnt - 下一个新增结点所在位置

a - 原数组

change函数中:p - 历史版本,q - 新版本

题目链接:可持久化线段树 1 
#include 
using namespace std;
int t[20000020], lson[20000020], rson[20000020], v[10000020], cnt = 2, a[10000005];
void build(int p, int l, int r) {
    if (l == r) {
        t[p] = a[l];
    } else {
        lson[p] = cnt++;
        rson[p] = cnt++;
        int m = l + r >> 1;
        build(lson[p], l, m);
        build(rson[p], m + 1, r);
        t[p] = t[lson[p]] + t[rson[p]];
    }
}
void change(int p, int q, int l, int r, int x, int d) {
    if (r < x || l > r) {
        lson[q] = lson[p];
        rson[q] = rson[p];
    } else if (l == r && l == x) {
        t[q] = d;
    } else {
        lson[q] = lson[p];
        rson[q] = rson[p];
        int m = l + r >> 1;
        if (x <= m) {
            lson[q] = cnt++;
            change(lson[p], lson[q], l, m, x, d);
        } else {
            rson[q] = cnt++;
            change(rson[p], rson[q], m + 1, r, x, d);
        }
        t[q] = t[lson[q]] + t[rson[q]];
    }
}
int query(int p, int l, int r, int ql, int qr) {
    if (l > qr || r < ql) {
        return 0;
    } else if (ql <= l && r <= qr) {
        return t[p];
    } else {
        int m = l + r >> 1;
        return query(lson[p], l, m, ql, qr) + query(rson[p], m + 1, r, ql, qr);
    }
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    build(1, 1, n);
    v[0] = 1;
    for (int i = 1; i <= m; i++) {
        int vi, op, x, d;
        cin >> vi >> op;
        if (op == 1) {
            cin >> x >> d;
            v[i] = cnt++;
            change(v[vi], v[i], 1, n, x, d);
        } else {
            cin >> x;
            v[i] = v[vi];
            cout << query(v[vi], 1, n, x, x) << endl;
        }
    }
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/304343.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号