线段树入门

一、引入

1.我想单点查询序列的值,怎么办?
当然是来一个数组啦!

2.我想单点查询序列的值,还想单点修改,怎么办?
还是数组!

3.我想区间求和(后文称为查询),怎么办?
维护一个前缀和,(sum[i]=sum_{j=1}^ia[i])就可以(O(1))查询。

4.我想区间求和,还想单点修改,怎么办?
退役吧。。

如果你至今还抱着万物皆可(O(1))的幻想,那就(Too\,young\,too\,simple)了。

我来帮你复习一下:

1.OI( o)计算机( o)二进制( o O(log_2n))

2.(OI o ext{(幻视)} 01 o ext{二进制}) ( o) (O(log_2n))

“二进制”思想在算法中应用广泛,从二分到倍增等,都化(n)(log_2n),避免了被卡飞的惨剧。所以就有了神奇的树状数组。

【注:你说差分?太强了,没听说过。】

二、定义

5.现在毒瘤出题人要求你区间查询,区间修改。这类问题可以用线段树来解决。
听说你树状数组很6,甚至还会差分??


【注:图片来自百度百科,但是看上去百度百科也是侵权的w我就不删了】

图中的巨型树状物就是一颗线段树。也就是说,将一个大区间取中点得到小区间,组成一颗二叉树,这就叫线段树。

三、毒瘤操作

1.区间查询

这和树状数组大同小异。将大区间拆成至多(log_2n)个小区间(n为区间总长),就可以拼凑出答案。实现方法是分治:如果孩子区间与所求区间有重叠,就继续向下查询,直到孩子区间包含在所求区间内,此时累加答案。

2.区间修改

woc这是(O(n))!

还真的是。那怎么办呢?我们先不考虑这个问题。

2.1单点修改很水

直接将对应的(log_2n)个节点修改就好了。
学到这里,你应该能A一道模板题了。

2.2我好想和区间查询一样快啊

对于一个不在线段树最底层的区间,在修改时,我们要把他的孩子一起更新。此时应该思考两个问题:

(1)如果我不用查询,更新孩子干嘛?

(2)如果我修改上了瘾,为什么不能把修改的内容累计,等到最后一起修改?

它们分别说明:

(1)要查询了,再来修改。

(2)不查询时,记录修改即可。

于是我们对于每一个节点,都记录一个标记(tag),在更新时只修改父亲节点的值,并把修改的内容记录到(tag)里。当查询到该节点时,顺手把子节点更新并下传标记。这样就不用连着孩子更新。
模板题

四、模板++

有时候维护的内容较多,就需要更复杂的代码。当然这些也属于模板题。

比如

(19-7-21未完待续)

原文地址:https://www.cnblogs.com/ehznehc/p/11221247.html