树状数组 区间修改 区间查询 思绪整理

树状数组真是强啊嘤嘤嘤。

介绍区间修改+区间查询之前一定要说一下区间修改+单点查询。

原本树状数组只能用于单点修改+区间查询。但是把原数组的差分数组做成树状数组就可以做到区间修改+单点查询。

即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的关系来看。

猜你喜欢

转载自blog.csdn.net/qq_39304630/article/details/81428611