本文是高级数据结构系列第3篇。
从这一篇开始,是一些区间数据结构。
引入
维护一个数列
- A x y:表示把
ax 加上y 。 - Q l r:表示询问
∑ri=lai 的值。
数列长度为
使用各种数据结构的时间复杂度如下表:
原数组 | 前缀和 | 树状数组 | |
---|---|---|---|
A操作 |
|
|
|
Q操作 |
|
|
|
从上表看出,无论是对于哪种操作,树状数组都有不俗的时间复杂度表现,因此,树状数组擅长解决这个问题。
介绍
来观察一下这个图。
我们假设原数组是
如果我们把
以上内容部分参考百度百科
然后问题就是,怎么知道这个实际数值呢?
根据二进制补码的原理,我们知道
修改与查询
修改
讲了这么多,终于进入正题了。再看一眼上面那个图:
如果我们要把
答案是,
根据观察,发现下标每次增加的量也是
inline int lowbit(int x){
return x&-x;
}
inline void add(int x,int y){
//向a[x]加y。
while (x<=n){
c[x]+=y;
x+=lowbit(x);
}
}
查询
和修改十分类似。自己观察上图。
inline int ask(int x){
int ans=0;
while (x){
ans+=c[x];
x-=lowbit(x)
}
}
应用
- 求逆序对
- 等等