图文详解二维差分
创始人
2024-05-01 15:00:35
0

目录

前言

一、 二维差分的定义

二、二维差分的使用

三、计算二维差分

四、ACWing 798. 差分矩阵



前言

一维+二维前缀和详解

图文详解一维差分

一、 二维差分的定义

对于一个给定的二维数组 arr,它的二维差分数组 d 中 d[i][j] 可以用如下公式计算

d[0][0] = arr[0][0],i,j == 0

② d[0][j] = arr[0][j] - arr[0][j - 1],i == 0,j >= 1

③ d[i][0] = arr[i][0] - arr[i - 1][0],i >= 1,j == 0

d[i][j] = arr[i][j]-arr[i-1][j]-arr[i][j-1]+arr[i-1][j-1],i,j>= 1

实际上,上面的公式是通过二维数组 arr 是二维差分数组的前缀和这个条件推导出来的,因此,不像一维差分定义那样直观。

二、二维差分的使用

二维差分的主要用处:快速地将一个区块中的所有元素都加上一个值 v

使用差分可以将在数组 arr 上的区块操作转化为在差分数组 d 上的单点操作。转换方式如下

假设区块左上角坐标为 (x1, y1),右下角坐标为 (x2, y2),对该区块中的每个元素都加上 v 等价于下面四个操作:

1.d[x1][y1] += v

2.d[x2 + 1][y1] -= v

 

 3.d[x1][y2 + 1] -= v

4.d[x2 + 1][y2 + 1] += v

 因为差分数组的前缀和相当于原数组,所以对差分数组进行以上四个单点操作后,就相当于给数组 arr 的区块加上一个值 v。

三、计算二维差分

通过定义计算二维差分比较复杂,可以使用一种更巧妙的方法:将二维差分中的每个元素一个一个地插进去

  1. 首先假设原二维数组 arr 的元素全为 0,那么二维差分数组 d 的元素显然也全为 0,这样完全符合定义。

  2. 接下来将 arr 中的每个元素依次更新为实际值。例如 arr[2][3] 的实际值为 5,那么就相当于给以 (2, 3) 坐标为左上角,(2, 3) 坐标为右下角的区块中的所有元素加上 5

    ① d[2][3] += 5

    ② d[3][3] -= 5

    ③ d[2][4] -= 5

    ④ d[3][4] += 5

    这样便得到了整个差分数组。

四、ACWing 798. 差分矩阵

题目描述

输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1, y1, x2, y2, c,其中 (x1, y1) 和 (x2, y2) 表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上 c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数 n, m, q。

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含 5 个整数 x1, y1, x2, y2, c,表示一个操作。

输出格式

共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1 ≤ n, m ≤1000, 1 ≤ q ≤100000, 0 ≤ x1 ≤ x2 ≤ n - 1, 0 ≤ y1 ≤ y2 ≤ m - 1, −1000 ≤ c ≤ 1000, −1000 ≤ 矩阵内元素的值 ≤ 1000

输入样例

3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
0 0 1 1 1
0 2 1 2 2
2 0 2 3 1

输出样例

2 3 4 1
4 3 4 1
2 2 2 2

代码实现: 

#include int arr[1000][1000];  
int d[1001][1001];void insert(int x1, int y1, int x2, int y2, int c)
{d[x1][y1] += c;d[x2 + 1][y1] -= c;d[x1][y2 + 1] -= c;d[x2 + 1][y2 + 1] += c;
}int main()
{int n = 0, m = 0, q = 0;scanf("%d %d %d", &n, &m, &q);int i = 0;int j = 0;// 输入整数矩阵,并计算二维差分for (i = 0; i < n; i++){for (j = 0; j < m; j++){scanf("%d", &arr[i][j]);insert(i, j, i, j, arr[i][j]);}}// 进行 q 次操作while (q--){int x1 = 0, y1 = 0, x2 = 0, y2 = 0;int c = 0;scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &c);insert(x1, y1, x2, y2, c);}	// 计算二维差分的前缀和,即原二维数组 arrarr[0][0] = d[0][0];for (j = 1; j < m; j++){arr[0][j] = arr[0][j - 1] + d[0][j];}for (i = 1; i < n; i++){arr[i][0] = arr[i - 1][0] + d[i][0];}for (i = 1; i < n; i++){for (j = 1; j < m; j++){arr[i][j] = arr[i - 1][j] + arr[i][j - 1] - arr[i - 1][j - 1] + d[i][j];}}// 输出for (i = 0; i < n; i++){for (j = 0; j < m; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...