树状数组(Binary Indexed Tree,BIT)
转自大牛柳婼 の bloghttps://www.liuchuo.net/archives/2268
- 本质上是按照二分对数组进行分组,维护和查询都是O(lgn)的复杂度
- 树状数组与线段树:树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。
- lowbit
- lowbit = x & (-x)
- lowbit(x)也可以理解为能整除x的最大的2的幂次
- c[i]存放的是在i号之前(包括i号)lowbit(i)个整数的和(即:c[i]的覆盖长度是lowbit(i) )
- 树状数组的下标必须从1开始
单点更新,区间查询
int getsum(int x)函数:返回前x个整数之和
1
2
3
4
5
6
|
int
getsum
(
x
)
{
sum
=
0
;
for
i
;
>=
1
-=
lowbit
(
)
)
+=
c
[
i
]
;
return
sum
;
}
|
- 如果要求[x,y]之内的数的和,可以转换成getsum(y) – getsum(x – 1)来解决
void update(x,v)函数:将第x个数加上一个数v
1
2
3
4
|
void
update
(
int
x
,
v
)
{
for
i
=
;
<=
n
+=
lowbit
(
)
)
c
[
i
]
;
}
|
经典应用:统计序列中在元素左边比该元素小的元素个数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <cstdio>
#include <cstring>
const
maxn
10010
;
#define lowbit(i) ((i) & (-i))
maxn
;
void
update
,
v
{
<
)
]
;
}
{
;
)
@H_415_404@
;
;
}
main
(
{
n
;
scanf
(
"%d"
&
;
i
++
{
;
;
printf
"%d\n"
x
-
;
}
;
如果是求序列第k大的问题:可以用二分法查询第一个满足getsum(i) >= k的i
|