树状数组
树状数组支持的基本操作:单点修改,前缀和查询
一维树状数组
单点修改,区间查询
对于单点修改,直接修改即可。
对于区间查询,拆成 \(sum(r)-sum(l-1)\) 来做。
区间修改,单点查询
考虑在原序列的差分序列上建立树状数组。
于是单点修改转化为前缀和查询。区间修改转化为单点修改 \(tr[l]\gets tr[l]+val\),\(tr[r+1]\gets tr[r+1]-val\)。
单点修改,单点查询
只需要将单点修改看做长度为 \(1\) 的区间修改即可。
区间修改,区间查询
最毒瘤的一集,建议用线段树做。
我们依然要考虑序列 \(a\) 的差分数组 \(b\)。那么我们可以将区间查询拆成两个前缀和查询,于是只需要考虑查询 \(sum(x)\)。
于是
\[\begin{aligned} sum(x)&=\sum_{i=1}^x\sum_{j=1}^i b[j]\\ &=(x+i)\sum_{i=1}^xb[i]-\sum_{i=1}^xi\cdot b[i] \end{aligned} \]拆成两个树状数组维护,第一个树状数组维护前缀和 \(\sum b[i]\),第二个树状数组维护 \(\sum i\cdot b[i]\)。
我们考虑 \(a[i]\gets a[i]+v\)(\(\forall i \in [l,r]\)) 后 \(i\cdot b[i]\) 的变化。
\[a_{l-1}, a_l+v, a_{l+1}+v, \cdots, a_{r}+v,a_{r+1} \]\[\iff b_{l-1},b_l+v,b_{l+1},\cdots,b_r,b_{r+1}-v \]\[\iff (l-1)b_{l-1},l\cdot b_l\textcolor{cyan}{+l\cdot v},(l+1)\cdot b_{l+1},\cdots, r\cdot b_r, (r+1)\cdot b_{r+1}\textcolor{cyan}{-(r+1)\cdot v} \]于是我们在维护第二个数组时只需要使 \(l\cdot b[l]\gets l\cdot b[l]+l\cdot v\),\((r+1)\cdot b[r+1] \gets (r+1)\cdot b[r+1]-(r+1)\cdot v\) 即可。
二维树状数组
单点修改,区间查询
对于单点修改,直接修改即可。
对于区间查询,拆成 \(sum(x_2,y_2)-sum(x_1-1,y_2)-sum(x_2,y_1-1)+sum(x_1-1,y_1-1)\) 来做。
区间修改,单点查询
考虑在原序列的差分序列上建立树状数组。
于是单点修改转化为前缀和查询。区间修改转化为单点修改 \(tr[x_1,y_1]\gets tr[x_1,y_1]+val\),\(tr[x_2+1,y_1]\gets tr[x_2+1,y_1]-val\),\(tr[x_1,y_2+1]\gets tr[x_1,y_2+1]-val\),\(tr[x_2+1,y_2+1]\gets tr[x_2+1,y_2+1]+val\)。
单点修改,单点查询
只需要将单点修改看做长度为 \(1\) 的区间修改即可。
区间修改,区间查询
最最毒瘤的一集,建议用二维线段树做。
我们依然要考虑序列 \(a\) 的差分数组 \(b\)。那么我们可以将区间查询拆成四个前缀和查询,于是只需要考虑查询 \(sum(x,y)\)。
于是
\[\begin{aligned} sum(x,y)&=\sum_{i=1}^x\sum_{j=1}^{y}\sum_{k=1}^i\sum_{l=1}^{j} b[k,l]\\ &=\sum_{i=1}^x\sum_{k=1}^i\sum_{j=1}^{y}\sum_{l=1}^{j} b[k,l] \\ &=\sum_{i=1}^x\sum_{k=1}^i\left((y+1)\sum_{j=1}^{y}b[i,j]-\sum_{j=1}^y j\cdot b[i,j] \right) \end{aligned} \]不妨设 \(c[i]=(y+1)\sum_{j=1}^{y}b[i,j]-\sum_{j=1}^y j\cdot b[i,j]\),继续推导:
\[\begin{aligned} sum(x,y)&=\sum_{i=1}^x\sum_{k=1}^i c[k]\\ &=(x+1)\sum _{i=1}^{x} c[i]-\sum_{i=1}^x i\cdot c[i] \end{aligned} \]然后还原式子
\[sum(x,y)=(x+1)\sum_{i=1}^x \left((y+1)\sum_{j=1}^{y}b[i,j]-\sum_{j=1}^y j\cdot b[i,j] \right)-\sum _{i=1}^{x} i\cdot \left((y+1)\sum_{j=1}^{y}b[i,j]-\sum_{j=1}^y j\cdot b[i,j] \right) \]\[=(x+1)(y+1)\sum_{i=1}^x\sum_{j=1}^y b[i,j]-(x+1)\sum_{i=1}^{x}\sum_{j=1}^{y} j\cdot b[i,j]-(y+1)\sum_{i=1}^{x}\sum_{j=1}^{y} i\cdot b[i,j]+\sum_{i=1}^{x}\sum_{j=1}^{y} ij\cdot b[i,j] \]拆成四个树状数组维护即可。
标签:单点,树状,cdot,sum,tr,查询,修改,数组 From: https://www.cnblogs.com/Starrykiller/p/fenwick-tree.html