「学习笔记」树状数组

树状数组

操作

以下代码为树状数组最常用的几个操作

1. lowbit\mathrm{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;

以及……
区间修改可以树上差分。


概念

树状数组与线段树相似,效率上要比线段树高,但适用性却不如线段树。

定义一个数组TreeTree表示子树的叶子结点的权值之和,这样可以发现到:
Tree1=a1Tree_1 = a_1

Tree2=a1+a2Tree_2 = a_1 + a_2

Tree3=a3Tree_3 = a_3

Tree4=a1+a2+a3+a4Tree_4 = a_1 + a_2 + a_3 + a_4

Tree5=a5Tree_5 = a_5

Tree6=a5+a6Tree_6 = a_5 + a_6

Tree7=a7Tree_7 = a_7

Tree8=a1+a2+a3+a4+a5+a6+a7+a8Tree_8 = a_1 + a_2 + a_3 + a_4 + a_5 + a_6 + a_7 + a_8

\cdots

经过观察可以得出Treei=ai2k+1+ai2k+2++aiTree_i = a_{i-2^k+1} + a_{i-2^k+2} + \cdots + a_i


lowbit\mathrm {lowbit} 函数的意义是取为 xx 的二进制表达式中最低位的1所对应的值
树状数组本就是对于二进制的理解&运用,利用 lowbit\mathrm {lowbit} 我们可以快速遍历整棵树。


于是乎,树状数组还可以解决各种关于区间の问题。

posted @ 2019-08-05 21:25  willbe233  阅读(61)  评论(0)    收藏  举报