有时,我们要支持区间修改,区间查询。
线段树可以做到。
但是树状数组更好写。
1d的情况:
设(b[i]=a[i]-a[i-1])
则(a[i]=b[1]+...+b[i])
(a[1]+...+a[l]=(b[1])+(b[1]+b[2])+....(b[1]+...+b[l]))
(a[1]+...+a[l]=l*b[1]+(l-1)*b[2]+......+b[l]=sum((l-i+1)*b[i]))
如果我们维护(b[i])的和,((i-1)*b[i])的树状数组(c,d),就能维护(a)的前缀和,就能知道(a)的区间和。
这样子看上去功能比线段树少。
但是如果我们要维护区间乘积
线段树打标记要永久化。需要预处理出一种长度标记的幂次才能正确更新答案。这样子十分麻烦。
然而在区间乘法时,两个树状数组乘的值都是一定的,可以logn处理出来。
在区间查询时,我们可以算出b2的逆元,b1的逆元*(x+1)次,这个都能在查询后完成。
这样子比线段树更方便。
代码:
void ad(int x,int y){
for(int i=x;i<=n;i+=i&-i)
b1[i]+=y,b2[i]+=x*y;
}
int q(int x){
int r=0;
for(int i=x;i;i-=i&-i)
r+=(x+1)*b1[i]-b2[i];
return r;
}