这个我只做了非连通图,支持/v /h参数
具体原理也很简单,而且编程十分方便。
那就是积分图:
1 | 1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 | 1 |
假如上图是输入。然后我们就算对应的积分图。每个点都变成此点左上角所有点之和:
0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 2 | 3 | 4 | 5 |
0 | 2 | 4 | 6 | 8 | 10 |
0 | 3 | 6 | 9 | 12 | 15 |
0 | 4 | 8 | 12 | 16 | 20 |
0 | 5 | 10 | 15 | 20 | 25 |
这样的计算能在m*n复杂度内完成。这样带来的好处是,对于任意一个矩形,矩形内所有元素之和的计算就变得极其简单了。
0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 2 | 3 | 4 | 5 |
0 | 2 | 4 | 6 | 8 | 10 |
0 | 3 | 6 | 9 | 12 | 15 |
0 | 4 | 8 | 12 | 16 | 20 |
0 | 5 | 10 | 15 | 20 | 25 |
因为左上角区域要被减两次,所以要加回来:
元素之和 = 右下角 - 左下角 - 右上角 + 左上角
然后就能得到元素之和了。
关于/h /v 属性,只要把这个图扩展一下就行。横向和纵向都首尾相接变为原来的两倍。
/a属性。可以先标出每一块大于0的所有元素。然后以每一块为起点,寻找最近的一块区域。然后不断重复即可。