树状数组(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
]
;
}
|
经典应用:统计序列中在元素左边比该元素小的元素个数
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_40_404@
;
;
}
main
(
{
n
;
scanf
(
"%d"
&
;
i
++
{
;
;
printf
"%d\n"
x
-
;
}
;
如果是求序列第k大的问题:可以用二分法查询第一个满足getsum(i) >= k的i
@H_403_489@
4
|
5
6
7
8
9
10
11
|
|
|
|
{
)
;
1057. Stack (30)-PAT甲级真题(树状数组)
@H_403_489@
10
|
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <cstdio>
#include <stack>
#define lowbit(i) ((i) & (-i))
const
maxn
100010
;
using
namespace
std
;
;
stack
<
int
>
s
;
{
)
;
}
{
;
-=
)
;
;
}
PeekMedian
(
{
left
right
k
.
size
;
right
{
;
)
;
else
@H_502_1071@
;
}
printf
(
"%d\n"
left
;
}
main
{
temp
;
scanf
"%d"
&
;
char
str
[
15
;
i
++
{
"%s"
;
==
'u'
{
;
push
;
;
}
else
'o'
{
(
!
empty
{
top
-
;
;
pop
;
{
"Invalid\n"
;
}
{
)
;
else
;
}
}
;
}
|