线段树入门

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

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

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

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

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

我来帮你复习一下:

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

2.\(OI \to \text{(幻视)} 01\to \text{二进制}\) \(\to\) \(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.heiqu.com/wpydys.html