树状数组使用总结
在考试中 因为不清楚二维树状数组怎么用 而失手了无数遍了...
今天终于把这个坑填了.... =_=
1.区间修改+单点查询(一维)
把查询第(x)个位置的值(s_x)变为查询前缀和(s_x = sum_{i = 1}^x d(i))。
其中 (d(x) = s_x - s_{x-1})。
修改([L,R])的时侯,只需要修改 (L) 与 (R)+(1) 两个点。
2.区间修改+区间查询(一维)
查询([1,x]),则有:
所以用两个树状数组分别维护(sum d(i))与(sum d(i)*i)即可。
3.单点修改+区间查询(二维)
直接维护((1,1))到((x,y))的这个矩阵的和即可。 代码类似一维处理即可:
for( x ; x <= n ; x += lowbit(x) )
for( y ; y <= m ; y += lowbit(y) )updata or query
查询时用一下二维前缀和容斥一下就行了。
4.区间修改+单点查询(二维)
一样的转为差分值:(s_{{x,y}} = sum_{i = 1}^x sum_{j=1}^y d(i,j))
其中$d(i,j) = s_{{x,y}} - s_{{x-1,y}} - s_{{x,y-1}} + s_{{x-1,y-1}} (
修改时只修改)(x_1,y_1)(、)(x_1,y_2+1)(、)(x_2+1,y_1)(、)(x_2+1,y_2+1)$
查询时一样的用 单点修改+区间查询(二维) 的方法查询。
5.区间修改+区间查询(二维)
把后面两个(sum)提到前面来:
展开后得到:
$res = res $
$+(x+1)(y+1) [ sum_{i=1}^x sum_{j=1}^y d(i,j) ] ( )- (x+1) [ sum_{i=1}^x sum_{j=1}^y d(i,j)j ]( )- (y+1)* [ sum_{i=1}^x sum_{j=1}^y d(i,j)i ]( )+ [ sum_{i=1}^x sum_{j=1}^y d(i,j)ij ]( 所以用四个树状数组分别维护)sum d()$ , (sum d()i) , (sum d()j) , (sum d()ij) 即可 , 具体实现戳这里。