Main Idea
本文主要来讲解二维树状数组的一些用法以及例题讲解。
Problem′s Website
T3:上帝造题的七分钟(洛谷)
Solution
我们按照操作的类型来说,必要时再解释例题。
1.基本概念
首先对于普通的一维树状数组,我之前有过粗略的介绍,不懂的同学可以先去学习一下。
那我们来说一下二维树状数组的定义,我们定义ta[i][j]为以(i,j)为右下角,且高度为lowbit(i),宽度为lowbit(j)的矩阵的和。
感觉还是比较好理解的。。。
2.单点修改区间查询
这是二维树状数组最基础的操作。
单点修改类似于一维树状数组,只不过是双重循环而已,而查询类似于二维前缀和,例如,输出左上角为(x1,y1),右下角为(x2,y2)矩阵的和,公式为ans=ask(x2,y2)−ask(x2,y1−1)−ask(x1−1,y2)+ask(x1−1,y1−1)
不懂的同学可以画个图模拟一下。
这也就是T1的题解。
代码会放在最后面。
3.区间修改单点查询
还是类似于一维树状数组此种操作,差分,仿照着二维前缀和,我们现在令ta[i][j]为a[i][j]与a[i−1][j]+a[i][j−1]−a[i−1][j−1]的差,求值时,我们直接求前缀和即可,那么如何修改?
例如,我们要修改左上角为(x1,y1),右下角为(x2,y2)的矩阵统一加上num,我们要在(x1,y1)加上num,因为它比(x1−1,y1) (x1,y1−1) (x1−1,y1−1)多了num,要在(x2+1,y1)减去num,因为它之前多加了一个num,同理,要在(x1,y2+1)减去num,最后要在(x2+1,y2+1)加上num,因为它多减了一个num,如果我这样描述还不懂,建议画图理解。
本种操作暂未例题。。。
代码会放在后面。
4.区间修改区间查询
这就是最终的操作了,根据上文,我们不难推出式子ans=x∑i=1y∑j=1i∑k=1j∑l=1ta[k][l],怎么那么长啊。。。
我们来缩短一下,经过模拟发现,ta[1][1]被计算了x×y次,ta[1][2]被计算了x×(y−1)次,ta[2][1]被计算了(x−1)×y次,所以我们可以推出ta[i][j]计算了(x−i+1)×(y−j+1)次,于是式子就被化简成了ans=x∑i=1y∑j=1ta[i][j]×(x−i+1)×(y−j+1),我们再把这个式子展开,得到ans=x∑i=1y∑j=1ta[i][j]×(x+1)×(y+1)−x∑i=1y∑j=1ta[i][j]×i×(y+1)−x∑i=1y∑j=1ta[i][j]×j×(x+1)+x∑i=1y∑j=1ta[i][j]×i×j
那么我们只需要开四个树状数组,即:ta[i][j],ta[i][j]×i,ta[i][j]×j,ta[i][j]×i×j
以上就是T2和T3的题解。
下面就是你们最期待的代码。
Code
- T1
1 | //Coded by Dy. |
- 区间修改单点查询
1 | //Coded by Dy. |
- T2
1 | //Coded by Dy. |
- T3
1 | //Coded by Dy. |
rp++
Related Issues not found
Please contact @dyrisingsunlight to initialize the comment