大体上可以分为两种:
一
每次修改的是一个点,所求的是关于某段区间;
这种情况最好办;比如说poj2352 stars;求每个点前面比他小的点的个数;
只用设置数组a[],先全是0,然后有某个点就依次修改,并以此统计;
这一种是最基本的向上修改,向下统计;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
二
每次修改的是一个区间,所求的值是关于某个点的;
代表的典型题目是HOJ1556 color the ball;
这个题是每次修改了一整个区间,最后求的是每个点修改的次数;
这个需要将上面的函数,稍加修改;
对于[s,t],要向下修改,将它的区间[0, t]都加一遍update(t);再向下修改,把不必要的区间[0, s)再减去update(s-1);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
注意
对于一,可以用于计算统计子树;
对于二,可以用于计算统计树上某个节点的所有祖先节点
poj3321
这题难的不是树状数组,主要是映射到树状数组。
建树,然后dfs一次就可以算出对某个节点它的第一个下标(在树状数组中)和最后一个下标。那个更改的时候就用这两个下标就行了。
类似于将树向右倾斜,dfs建好树后c子树的第一个下标是4,最后一个下标是7。统计子树时只要sum(7)-sum(4-1)
foj2176
是poj3321加强版,一样的建树,但是节点要存k个值,然后update和sum的时候注意取和dep的差值,注意update减去val时的dep不要取错,update(le[i], dep[ri[i]], -val);
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 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
|