关于可持久化线段树的一些研究(链表实现)

    本人蒟蒻一只……近日终于弄懂了可持久化线段树的一些东西……写下来分享一下=w=

    首先要谈可持久化线段树,你肯定得懂线段树吧。这里就不提线段树了……可持久化线段树是什么东西呢?就是对线段树的叶子节点做m次修改,同时做n次询问,但这些询问会问你的东西是做了第i次修改时XXXXX。举个例子,给你一列数,a1,a2,a3...an,给定两种共m个操作:1、修改一个数的值;2、询问做了第k次修改后,第i到第j个数中最大的是多少(保证已经做了至少k次修改)。(n<=100000,m<=100000)

    如果无视掉第二个询问的第一句话(第k次修改后),那么题目还是很水的啦=w=,不过加上似乎就有些问题了。但我们可以用一个笨办法!什么呢?就是把以前所有线段树的版本全部都记录下来。这样查询复杂度和以前不变,时间什么的还是有保证的!

    但很可惜,这样你要存m棵线段树,每棵线段树至少要2n个节点,那么2*100000*100000个节点……早就不知道空间炸到哪里去了=w=。

    所以我们需要更优秀的办法。仔细观察我们就会发现,每次修改一个节点的权值,其实所涉及到的节点最多也就一条链(修改ai的权值,影响的最多也就是ai,ai的fa……),而其它所有节点的权值都没有变。比如下图序列36854252,如果修改了5的权值,那么它最多能够影响的是以绿色为底的一条链。(下图直接用左右儿子点权较大的代替当前节点点权)

    那么我们新开一棵树存白色的节点就完全没有意义了。所以对于每一个节点,我们用链表的方式将其存储下来。每一次修改我们新建一条链,同时将根节点保存下来,然后按顺序修改。什么意思呢?就是root[i],表示第i次修改后的根节点,若上图,假设5被修改了(比如本来是3),root[i]=8的左儿子节点存的就是root[i-1]的左儿子节点(也是8),它的右儿子就是新的节点5,而5的左儿子又是root[i-1]中root=8的右儿子的左儿子4,而5的右儿子是新的节点5……直到完全建成这样一条链,而我们新开的节点其实也就logn个。这样空间上就有了保证。

    不会链表的都给我面壁思过去=w=

    ……好吧是我太弱了,只会搞链表……(当然用数组模拟链表也是非常兹词的=w=)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值