树状数组
操作
以下代码为树状数组最常用的几个操作
1. l o w b i t \mathrm{lowbit} lowbit
function lowbit(x:longint):int64;
Begin
exit(x and (-x));
end;
2. 单点修改
procedure replace(x,y:int64);
Var i:int64;
Begin
i:=x;
interim[x]:=y;
while i<=n do
Begin
tree[i]:=y;
i:=i+lowbit(i);
end;
end;
3. 区间查询
function get_summation(x:longint):int64;
Var i:int64;
Begin
get_summation:=0;
i:=x;
while i>0 do
Begin
get_summation:=get_summation+tree[i];
i:=i-lowbit(i);
end;
exit(get_summation);
end;
4.区间极值
function get_maximum(x,y:int64):int64;
Var i:int64;
Begin
get_maximum:=0;
i:=y;
while i>=x do
Begin
get_maximum:=max(interim[i],get_maximum);
i:=i-1;
while i-lowbit(i)>=x do
Begin
get_maximum:=max(tree[i],get_maximum);
i:=i-lowbit(i);
end;
end;
exit(get_maximum);
end;
以及……
区间修改可以树上差分。
概念
树状数组与线段树相似,效率上要比线段树高,但适用性却不如线段树。
定义一个数组
T
r
e
e
Tree
Tree表示子树的叶子结点的权值之和,这样可以发现到:
T
r
e
e
1
=
a
1
Tree_1 = a_1
Tree1=a1
T r e e 2 = a 1 + a 2 Tree_2 = a_1 + a_2 Tree2=a1+a2
T r e e 3 = a 3 Tree_3 = a_3 Tree3=a3
T r e e 4 = a 1 + a 2 + a 3 + a 4 Tree_4 = a_1 + a_2 + a_3 + a_4 Tree4=a1+a2+a3+a4
T r e e 5 = a 5 Tree_5 = a_5 Tree5=a5
T r e e 6 = a 5 + a 6 Tree_6 = a_5 + a_6 Tree6=a5+a6
T r e e 7 = a 7 Tree_7 = a_7 Tree7=a7
T r e e 8 = a 1 + a 2 + a 3 + a 4 + a 5 + a 6 + a 7 + a 8 Tree_8 = a_1 + a_2 + a_3 + a_4 + a_5 + a_6 + a_7 + a_8 Tree8=a1+a2+a3+a4+a5+a6+a7+a8
⋯ \cdots ⋯
经过观察可以得出 T r e e i = a i − 2 k + 1 + a i − 2 k + 2 + ⋯ + a i Tree_i = a_{i-2^k+1} + a_{i-2^k+2} + \cdots + a_i Treei=ai−2k+1+ai−2k+2+⋯+ai
l
o
w
b
i
t
\mathrm {lowbit}
lowbit 函数的意义是取为
x
x
x 的二进制表达式中最低位的1所对应的值
树状数组本就是对于二进制的理解&运用,利用
l
o
w
b
i
t
\mathrm {lowbit}
lowbit 我们可以快速遍历整棵树。
于是乎,树状数组还可以解决各种关于区间の问题。