必备算法模版之树状数组

作者: | 更新日期:

一个轻巧而有用的数据结构。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

一、背景

之前我分享 leetcode 算法比赛题解的时候,经常会提到这个题裸用树状数组就过了,那个题裸用线段树就过了。

那怎么裸用呢?
现场根据自己的硬实力敲一个树状数组或者线段树吗?

不是的。
这些固定的算法都有固定的代码,没必要重复敲一遍。
直接从代码库里复制过来就行了。

这里的代码库我们称为模版。

今天给大家分享一个树状数组的模版库。

二、树状数组解决什么问题

先来看一个问题。

假设这里有一个数组,有两个操作。

1)修改某个位置的值。
2)求某个区间和。

正常情况下,修改的复杂度是O(1),查询的复杂度是O(n)
如果有 m 个操作,那总复杂度就是 O(nm)了。

而通过树状数组,修改和查询的复杂度都是O(log(n))
这样总复杂度就是O(m log(n))了。

所以树状数组主要用来解决单点更新、前缀查询的问题。
而两个前缀和求差就是区间和,所以也可以解决区间问题。

三、树状数组的原理

树状数组的本质是分治法,即将问题拆分为若干个字问题逐个解决,最后合并得到答案。

具体原理上,按照 bit 位拆分子问题的。

更新的时候,复杂度之所以是 log 级别的,就是需要更新所有的父问题。
如上图,更新 5 的时候,需要更新 6,需要更新 8,一直需要更新到 maxn,最多有 log(n) 个父问题。

如上图,查询 8 的时候,可以直接O(1)得到答案。
而查询 7 的时候,会拆分为三个子问题:764 直接相加得到答案,最多可以拆分为 log(n)个子问题。

四、树状数组的模版

树状数组可以封装为一个对象,提供初始化、更新、查询三个方法。

这样,你需要使用树状数组的时候,创建一个对象即可。

五、最后

这里给大家分享了树状数组的模版,代码具体位置在如下,感兴趣的可以自己去获得文本的模版。

文本模版地址: https://github.com/tiankonguse/ACM/blob/master/tmpleate-2020/code/treeArray.cc

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越