树状数组
树状数组
树状数组支持的基本操作:单点修改,前缀和查询
一维树状数组
单点修改,区间查询
对于单点修改,直接修改即可。
对于区间查询,拆成 \(sum(r)-sum(l-1)\) 来做。
区间修改,单点查询
考虑在原序列的差分序列上建立树状数组。
于是单点修改转化为前缀和查询。区间修改转化为单点修改 \(tr[l]\gets tr[l]+val\),\(tr[r+1]\gets tr[r+1]-val\)。
单点修改,单点查询
只需要将单点修改看做长度为 \(1\) 的区间修改即可。
区间修改,区间查询
最毒瘤的一集,建议用线段树做。
我们依然要考虑序列 \(a\) 的差分数组 \(b\)。那么我们可以将区间查询拆成两个前缀和查询,于是只需要考虑查询 \(sum(x)\)。
于是
拆成两个树状数组维护,第一个树状数组维护前缀和 \(\sum b[i]\),第二个树状数组维护 \(\sum i\cdot b[i]\)。
我们考虑 \(a[i]\gets a[i]+v\)(\(\forall i \in [l,r]\)) 后 \(i\cdot b[i]\) 的变化。
于是我们在维护第二个数组时只需要使 \(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)\)。
于是
不妨设 \(c[i]=(y+1)\sum_{j=1}^{y}b[i,j]-\sum_{j=1}^y j\cdot b[i,j]\),继续推导:
然后还原式子
拆成四个树状数组维护即可。

浙公网安备 33010602011771号