这个我只做了非连通图,支持/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的所有元素。然后以每一块为起点,寻找最近的一块区域。然后不断重复即可。