树状数组真是强啊嘤嘤嘤。
介绍区间修改+区间查询之前一定要说一下区间修改+单点查询。
原本树状数组只能用于单点修改+区间查询。但是把原数组的差分数组做成树状数组就可以做到区间修改+单点查询。
即C[i]=A[i]-A[i-1](A[0]=0),然后把C数组建成树状数组C ' ;这样对于A[i]就可以用Sum(C ' [j] (j=1->i) )求得,利用树状数组性质可以logn求得结果。
考虑如下式子:Sum(A[i] (i=1->j) )=j*C[1]+(j-1)*C[2]+……+1*C[j];
j*A[j]-Sum(A[i] (i=1->j) )=0*C[1]+1*C[2]+……+(j-1)*C[j];
于是我们可以用数组D[i]=(i-1)*C[i]做成树状数组维护结果;
Sum(A[i] (i=1->j) )=j*getsum(A,j)-getsum(D,j);
求原数组区间和的时候 Sum(A[i] (i=L->R) )=Sum(A[i] (i=1->R) )-Sum(A[i] (i=1->L-1) );代入方法即可。
重点是两个数组的更新:
差分树状数组C ' 的更新:当给[L,R]增加x时,只需要从C ' [L]增加x并向上lowbit增加x,并且从C ' [R+1]增加-x并向上lowbit增加-x即可。
维护数组的更新:首先可知D[i]=(i-1)*C[i]; 当差分数组更新增量x的时候,例如C[L]增加了x,L的累加lowbit的位置的C也要累加x,那么由于D[i]=(i-1)*C[i];这些位置对应的D也要同时增加(L-1)*x;
问题是为什么对于D[R+1]是向上累加R*x。
我们知道D数组是同比与C数组变换的。在区间更新的时候,仅仅是让C[L]增加了x,C[R+1]增加了-x,为了让D数组同比与C数组变化,所以D[R+1]应该向上累加R*(-x);
应该保持的原则是这样的,C是差分数组,D[i]=(i-1)*C[i] 所以在变换的时候,我们更应该关注的是原数组,而不是做成树状数组的数组。我们只是按照树状数组的方式向上更新,但是初始点是哪个,具体更新多少是根据原数组C和D的关系来看。