当前位置: 首页 > article >正文

前缀和2️⃣-二维前缀和

题目链接:**【模板】二维前缀和_牛客题霸_牛客网**

题目描述:

解法:

算法思路:

类比于一维数组的形式,如果我们能处理出来从[0, 0] 位置到 [i, j] 位置这片区域内所有元素的累加和,就可以在O(1) 的时间内,搞定矩阵内任意区域内所有元素的累加和。因此我们接下来仅需完成两步即可:

◦ 第一步:搞出来前缀和矩阵

这里就要用到一维数组里面的拓展知识,我们要在矩阵的最上面和最左边添加上一行和一列0,这样我们就可以省去非常多的边界条件的处理处理后的矩阵就像这样:

 

这样,我们填写前缀和矩阵数组的时候,下标直接从1开始,能大胆使用i - 1 ,j - 1 位置的值。

注意 dp 表与原数组 matrix 内的元素的映射关系:

从dp 表到 matrix 矩阵,横纵坐标减一;

从matrix 矩阵到 dp 表,横纵坐标加一。

前缀和矩阵中 sum[i] [j]的含义,以及如何递推二维前缀和方程

◉ sum[i] [j]的含义:

sum[i] [j] 表示,从下图的红色区域:[0, 0] 位置到 [i, j] 位置这段区域内,所有元素的累加和。对应下图的红色区域:

递推方程:其实这个递推方程非常像我们小学做过求图形面积的题,我们可以将 [0, 0] 位置到 [i, j]位置这段区域分解成下面的部分: 

sum[i] [j] = 红 + 蓝 + 绿 + 黄,分析一下这四块区域:

✸ 黄色部分最简单,它就是数组中的 matrix[i ] [j ] (注意坐标的映射关系)

✸ 单独的蓝不好求,因为它不是我们定义的状态表示中的区域,同理,单独的绿也是;

✸ 但是如果是红 + 蓝,正好是我们dp 数组中 sum[i - 1] [j] 的值,美滋滋;

✸ 同理,如果是红 + 绿,正好是我们dp 数组中 sum[i] [j - 1] 的值;

✸ 如果把上面求的三个值加起来,那就是黄 + 红 + 蓝 + 红 + 绿,发现多算了一部分红的面积,因此再单独减去红的面积即可;

✸ 红的面积正好也是符合 dp 数组的定义的,即 sum[i - 1] [j - 1]

综上所述,我们的递推方程就是:

sum[i][j]=sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j -1]+matrix[i][j]

 ◦ 第二步:使用前缀和矩阵

求[x1,y1]~[x2,y2]内值的和

为A+B+C+D - (A+B) - (A+C) + A

D = dp[x2] [y2] - dp[x1-1] [y2] - dp[x2] [y1-1] +dp[x1-1] [y1-1]

 C++算法代码:

#include <iostream>
using namespace std;
#include <vector>

int main() {
    //1.读入数据
    int n = 0, m = 0, q = 0;
    cin >> n >> m >> q;
    vector<vector<int>> arr(n+1, vector<int>(m+1));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> arr[i][j];

    //2.预处理前缀和矩阵
    vector<vector<long long>> dp(n+1, vector<long long>(m+1));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            dp[i][j] =  dp[i - 1][j] + dp[i][j - 1] + arr[i][j] - dp[i - 1][j - 1];
    
    //3.使用前缀和矩阵
    int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    while(q--){
        cin >> x1 >> y1 >> x2 >> y2;
        cout << dp[x2] [y2] - dp[x1-1] [y2] - dp[x2] [y1-1] +dp[x1-1] [y1-1] << endl;
    }

}
// 64 位输出请用 printf("%lld")


http://www.kler.cn/a/282709.html

相关文章:

  • 制作图片马常用的五种方法总结
  • centos7安装Chrome使用selenium-wire
  • 解决failed to execute PosixPath(‘dot‘) 或者GraphViz‘s executables not found
  • Unity教程(十八)战斗系统 攻击逻辑
  • AutoHotKey自动热键AHK-正则表达式
  • 【云原生系列--Longhorn的部署】
  • 先进制造aps专题二十五 openai的ai大模型设计也使用了aps用的并行遗传算法
  • Linux文件IO缓存
  • Linux(更新中~)
  • 【JVM原理】类加载机制
  • hadoop文件上传步骤
  • Golang | Leetcode Golang题解之第382题链表随机节点
  • 正则表达式pattern
  • 【CSS】选择器
  • GAN Inversion(GAN 反演)
  • vue项目中解决el-table数据过多导致页面卡顿问题
  • 学习系列三:V8目标检测与分割自动化标注
  • 数据库不停机迁移方案
  • 【SpringCloud Alibaba】(九)学习 Gateway 服务网关
  • Golang 教程2
  • 工作 6 年,@Transactional 注解用的一塌糊涂
  • 空间计量 | 空间杜宾误差模型SDEM
  • 基于RK3568平台opencv的图像采集、ffmpeg推流和Windows端拉流(多线程)
  • 新手教学系列——如何实现基于asyncio的高效率 Worker(按需获取任务、防止阻塞与崩溃)
  • 时序预测 | 基于WTC+transformer时间序列组合预测模型(pytorch)
  • 【河北航空-注册安全分析报告-无验证方式导致安全隐患】