zoukankan      html  css  js  c++  java
  • 二维前缀和详解

    引入

    还是先从例题引入,给你一个二维平面,要求在$Theta(1)$的时间复杂度内求出一个矩形内数的和。

    显然,对于极端情况,二维平面退化成一维,那么我么可以用前缀和数组轻松解决,放在二维平面有该怎么办呢?

    我们就要进入一个新的名词:二维前缀和


    何谓二位前缀和

    我们可以感性的将其理解为建立在二维平面上的前缀和,如下图:

    红色区域所有数的和即为二维前缀和中点$(i,j)$的值。


    如何预处理

    类比一维前缀和,我们可以在$Theta(n)$的时间复杂度下预处理,如下代码:

    a[i]+=a[i-1];
    

    那么对于二维前缀和,我们怎么预处理呢?

    先给出算式:

    Map[i][j]+=Map[i-1][j]+Map[i][j-1]-Map[i-1][j-1]; 

    类比一维前缀和,因为我们从左到右在计算$a[i]$的时候已经知道了$a[i-1]$的值,所以同理,我们从左上向右下在计算$Map[i][j]$的时候已经知道了它右上所有点的前缀和,也就是知道了$Map[i-1][j]$、$Map[i][j-1]$和$Map[i-1][j-1]$的值,那么现在考虑为什么要做如上的运算。

    其中,$Map[i][j]$的初始值即为点$(i,j)$的权值,如图:

    那么现在,我们要求前缀和,也就是要加上下图中橙色区域:

    而我们加上的$Map[i-1][j]$即为下图蓝色区域:

    加上的$Map[i][j-1]$即为下图绿色区域:

    然后我们会发现,有一部分重叠了,如下图紫色区域:

    而这部分就是我们要减去的$Map[i-1][j-1]$。

    那么我们的预处理就完成了。

    时间复杂度:$Theta(n imes m)$,与一维中的$Theta(n)$预处理同理。


    如何查询

    依然是类比一维前缀和,对于查询区间$(l,r)$的值,我们可以用如下代码进行$Theta(1)$的查询:

    sum=a[r]-a[l-1];
    

    也就是说,用右端点的前缀和值减去左端点$-1$的前缀和值即得到了区间$(l,r)$的和,如下图:

    那么对于二维前缀和,我们有应该怎么办呢?

    对于计算矩形$(x1,y1)sim (x2,y2)$的和,先给出如下算式:

    sum=Map[x2][y2]-Map[x1-1][y2]-Map[x2][y1-1]+Map[x1-1][y1-1];
    

    下面来理解算式:

    现在我们要求下图中红色区域的权值和:

    而我们已经预处理好了前缀和,但是我们还不直接知道矩形$(x1,y1)sim (x2,y2)$的权值和,那么我们考虑怎么减去那部分。

    我们已经知道了$Map[x2][y2]$,而我们需要减去下图中橙色区域:

    那么我们先减去$Map[x1-1][y2]$,也就是下图中蓝色区域:

    然后再减去$Map[x2][y1-1]$,也就是下图中绿色区域:

    然后,我们发现我们多减去了一部分,要把它加回来,而这部分就是$Map[x1-1][y1-1]$,如下图紫色部分:

    这样,我们就成功的得到了需要求和的部分的值。

    时间复杂度:$Theta(1)$,与一维前缀和的$Theta(1)$同理。


    例题

    那么现在对于二维前缀和的讲解就结束了,下面推荐几道我觉得不错的考察二维前缀和的题,大概$NOIP$难度:

    $alpha.$任(duty)

    还在完善……


    rp++

  • 相关阅读:
    一个ball例程带你进入 Halcon 世界
    新公民读本
    open_window()到底做了什么?
    duilib学习领悟(4)
    duilib学习领悟(3)
    duilib学习领悟(2)
    通过Vue路由传参的两种方式及Vue组件中接收参数的方式
    彻底研透javascript中的对象及面向对象编程
    thinkphp5中使用phpmailer实现发送邮件功能
    小程序和ThinkPHP5结合实现登录状态(含代码)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11461640.html
Copyright © 2011-2022 走看看