关于主席树

什么是主席树?

主席树又叫做可持久化线段树,其实后者才是它的大名只是大家都图方便就叫前者了。

可持久化线段树,一听名字就知道它的两个终点:可持久化,线段树。

都要学主席树了,线段树是什么总归都知道的吧,那什么是可持久化呢?

可持久化理解起来其实也很简单,说白了就是可以查询历史节点就可以叫可持久化了,所以可持久化线段树的意思就是可以查询线段树的历史节点就是可持久化了。

如何实现可持久化?

我们这边先给出一棵线段树吧。

画的不好,大家理解一下就行了

假设说我现在想要单点修改最左边的叶子节点

在这里插入图片描述

那么我们会发现只要修改这个叶子节点以及它所有的祖先节点这条链上的节点就行了,换句话说,我们只要把这条链上的节点保存下来下次查询就行了。

在这里插入图片描述
那我们的选择就是再开一个链,如果他的左节点被修改那么我们就指向他的左节点,右节点同理。

关于代码实现

上面其实已经差不多把主席树的原理讲完了,下面放一下具体的代码实现。

主席树的构建

struct node{int l, r, val;};
auto maketree = [&](auto self, int p, int l, int r) -> int {
    p = ++ cnt;
    if(l == r){
        tree[p].val = nums[l];
        return cnt;
    }
    int mid = (l + r) >> 1;
    tree[p].l = self(self, tree[p].l, l, mid);
    tree[p].r = self(self, tree[p].r, mid + 1, r);
    return p;
};

和线段树使用 x < < 1 x << 1 x<<1 x < < 1 ∣ 1 x << 1|1 x<<11不同主席树需要一个变量专门存左右节点,因为我们后面还需要开点,左右节点不一定会符合线段树的特性

主席树的单点修改

root[i] = update(update, root[v], 1, n, pos, val);
auto clone = [&](int p) -> int {tree[++ cnt] = tree[p]; return cnt;};
auto update = [&](auto self, int p, int l, int r, int x, int y) -> int {//当前节点 左右边界 目标节点 目标值
    p = clone(p);
    if(l == r){
         tree[p].val = y;
    }else{
         int mid = (l + r) >> 1;
         if(x <= mid) tree[p].l = self(self, tree[p].l, l, mid, x, y);
         else tree[p].r = self(self, tree[p].r, mid + 1, r, x, y);
    }
    return p;
};

我们之前说过如果左右节点被修改那么我们就将新的节点的编号更新它的左右节点。最后存下当前版本的根节点编号,用来下次查询时候使用。

主席树的单点查询

query(query, root[v], 1, n, pos)
auto query = [&](auto self, int p, int l, int r, int x) -> int {
    if(l == r) return tree[p].val;
    else{
        int mid = (l + r) >> 1;
        if(x <= mid) return self(self, tree[p].l, l, mid, x);
        else return self(self, tree[p].r, mid + 1, r, x);
    }
};

查询和线段树比较类似,只是要注意要从历史版本的根节点向下寻找。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值