二维前缀和(矩形割补法)——杨子曰算法

二维前缀和(矩形割补法)——杨子曰算法


今天曰一个很实用的技巧,二维前缀和
来,先问一个问题,如果我给出一个矩阵,让你求出任意一个子矩阵的和,你会怎么搞?
哦,简单简单,O(n^2)咔咔地暴力一下,欧了
要是真这么简单,我会问你吗?我们追求的是速度,做到O(n^2)读入后,O(1)搞定。


好的,你先要知道一个东西叫做前缀和,就是让你算出一个序列中子序列的和,
方法就是用f[i]存序列1~i的和,那么询问x,y,答案就是f[y]-f[x-1]
如果你已经知道了这个,我们就来讨论二维的情况吧
杨子曰:题目的思想是可以转移的,So在二维情况是我们同样用一个数组f[i][j]表示a[1,1]为左上角a[i][j]为左下角的子矩阵的和,如图这里写图片描述
f[3][4]就是表示绿色部分的和
知道了这个以后,我们就开始来看一看一个任意的以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵怎么求:
这里写图片描述
首先这个矩阵的和肯定包括在f[x2][y2]中,但是多了一些东西,所以我们要把蓝的,黄的,绿的部分减去,首先看如何减去蓝的,用最粗暴的方法,直接减掉f[x1-1,y2],好现在只要减掉一个绿色部分就行了,依然用简单粗暴的办法,减掉f[x2][y1-1]
噢,有人举起了手,可是黄色部分被减了两遍呀,不要紧张,加回去就得了呗,
So,杨子曰:子矩阵的和就等于f[x2][y2]-f[x1-1][y2]-f[x2][y1-1]+f[x1-1][y1-1]
这样我们,就做到了O(1)取到子矩阵的和
OK,完事

呵呵,代码才打了一个开头就打不下去了对吧,f[i][j]怎么预处理啊啊啊啊!
其实也是比较简单的,look at the图:
这里写图片描述
你要算出黄绿蓝,三个部分的和,你要知道,当你再算f[i][j]的时候已经算好了f[i-1][j],f[i][j-1],f[i-1][j-1]
所以先用f[i-1][j]+f[i][j-1],NO,黄色部分被夹了两边呀,额,一样的套路,减掉不就欧了吗,
So,杨子曰:f[i][j]=f[i-1][j]+f[i][j-1]-f[i][j]
这回是真的
OK,完事
于TJQ高层小区902

未经作者允许,严禁转载:https://blog.csdn.net/henryyang2018/article/details/79734675

猜你喜欢

转载自blog.csdn.net/henryyang2018/article/details/79734675
今日推荐