AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 798. 差分矩阵 【 c++详细题解 】    原题链接    简单

作者: 作者的头像   林小鹿 ,  2020-12-20 11:48:53 ,  所有人可见 ,  阅读 29470


548


326

二维差分

如果扩展到二维,我们需要让二维数组被选中的子矩阵中的每个元素的值加上c,是否也可以达到O(1)的时间复杂度。答案是可以的,考虑二维差分。

a[][]数组是b[][]数组的前缀和数组,那么b[][]是a[][]的差分数组

原数组: a[i][j]

我们去构造差分数组: b[i][j]

使得a数组中a[i][j]是b数组左上角(1,1)到右下角(i,j)所包围矩形元素的和。

如何构造b数组呢?

我们去逆向思考。

同一维差分,我们构造二维差分数组目的是为了 让原二维数组a中所选中子矩阵中的每一个元素加上c的操作,可以由O(n*n)的时间复杂度优化成O(1)

已知原数组a中被选中的子矩阵为 以(x1,y1)为左上角,以(x2,y2)为右下角所围成的矩形区域;

始终要记得,a数组是b数组的前缀和数组,比如对b数组的b[i][j]的修改,会影响到a数组中从a[i][j]及往后的每一个数。

假定我们已经构造好了b数组,类比一维差分,我们执行以下操作
来使被选中的子矩阵中的每个元素的值加上c

b[x1][y1] += c;

b[x1,][y2+1] -= c;

b[x2+1][y1] -= c;

b[x2+1][y2+1] += c;

每次对b数组执行以上操作,等价于:

for(int i=x1;i<=x2;i++)
  for(int j=y1;j<=y2;j++)
    a[i][j]+=c;

我们画个图去理解一下这个过程:

20201217174836198.png{:width=”57%”}

b[x1][ y1 ] +=c ; 对应图1 ,让整个a数组中蓝色矩形面积的元素都加上了c。
b[x1,][y2+1]-=c ; 对应图2 ,让整个a数组中绿色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y1]- =c ; 对应图3 ,让整个a数组中紫色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2+1][y2+1]+=c; 对应图4,,让整个a数组中红色矩形面积的元素再加上c,红色内的相当于被减了两次,再加上一次c,才能使其恢复。

20201217170336254.png
我们将上述操作封装成一个插入函数:

void insert(int x1,int y1,int x2,int y2,int c)
{     //对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}

我们可以先假想a数组为空,那么b数组一开始也为空,但是实际上a数组并不为空,因此我们每次让b数组以(i,j)为左上角到以(i,j)为右下角面积内元素(其实就是一个小方格的面积)去插入 c=a[i][j],等价于原数组a中(i,j) 到(i,j)范围内 加上了 a[i][j] ,因此执行n*m次插入操作,就成功构建了差分b数组.

这叫做曲线救国。

代码如下:

  for(int i=1;i<=n;i++)
  {
      for(int j=1;j<=m;j++)
      {
          insert(i,j,i,j,a[i][j]);    //构建差分数组
      }
  }

总结:

20201217172035975.png

AC代码

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
int a[N][N], b[N][N];
void insert(int x1, int y1, int x2, int y2, int c)
{
    b[x1][y1] += c;
    b[x2 + 1][y1] -= c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y2 + 1] += c;
}
int main()
{
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            insert(i, j, i, j, a[i][j]);      //构建差分数组
        }
    }
    while (q--)
    {
        int x1, y1, x2, y2, c;
        cin >> x1 >> y1 >> x2 >> y2 >> c;
        insert(x1, y1, x2, y2, c);
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];  //二维前缀和
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            printf("%d ", b[i][j]);
        }
        printf("\n");
    }
    return 0;
}

155 评论


用户头像
acrophobia   2022-01-30 23:06      86    踩      回复

其实我很纳闷的是,最后求前缀和不应该用a [i][j] = b[i][j]+ a[i-1][j] + a[i][j-1] - a[i-1][j-1];
cout << a[i][j]<<” “;这个式子吗,虽然最后是一样的结果,我也知道是转化的形式,但是Y总还有你们的题解都直接用差分数组直接得出结果,也不加以讲解说明,是不是对新手不友好呢。。卡了很久

用户头像
Toolman   2022-03-09 09:58      11    踩      回复

我也这么觉得!!!想了好久qwq

用户头像
soar_fish   2022-03-24 11:00      3    踩      回复

大佬搞懂了吗?我也卡在这里了,一维的题解还是用的前缀和的公式,二维的题解最后求前缀和这里就看不懂了。。。

用户头像
SunHT   2022-04-16 14:32      2    踩      回复

+1

用户头像
BaNg059   2022-05-25 11:14      3    踩      回复

只是一种方式,直接在b数组上做前缀和可以简化代码,引入额外的数组也没问题。

用户头像
Sugarfree_7   2022-06-12 14:18      8    踩      回复

借用楼上“Barbed”的回复:
差分这样构建的原因:首先假设a,b都为空数组,也就是全部为0的情况,那么我们也可以说,b数组是a数组的差分数组!因为a[i][j] = b[1][1]+…b[i][j],因为都是0,所有情况满足!在这时a数组其实不为空,我们把a数组中的值看作(0+a[i][j])那么a数组的值变了,变成了a[i][j],这时如果b数组要想成为a数组的差分数组,值也要变为a[i][j],所以我们把b[i][j]变为a[i][j],这样就能满足b数组是a数组的差分数组。也就相当于想b数组中插入a[i][j].

个人理解:所以b数组其实对应的值就是a数组的值,前缀和可替换为b

用户头像
不劳不获.   2023-02-01 22:21      3    踩      回复

问一下构建差分数组的代码,他的代码不是把a[][] copy 到 b[][]?

用户头像
两处闲愁.   2023-03-14 11:32    回复了 不劳不获. 的评论      1    踩      回复

不是的,虽然我也没太明白

用户头像
Lsf321   2023-04-17 22:27      34    踩      回复
#include <iostream>
using namespace std;

const int N = 1e3 + 10;
int n, m, q;
int a[N][N], b[N][N];

void insert(int x1, int y1, int x2, int y2, int c)
{
    b[x1][y1] += c;
    b[x2 + 1][y1] -= c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y2 + 1] += c;
}

int main(){
    // ios::sync_with_stdio(false); //提高cin读取速度,不能使用scanf
    scanf("%d%d%d", &n, &m, &q); // n行m列,q次
    for(int i = 1; i <= n; i++){
        for (int j =1; j <= m; j++){
            scanf("%d", &a[i][j]);
        }
    }
    // 构建差分数组
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            b[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];
        }
    }
    while (q--){
        int x1, y1, x2, y2, c;
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
        insert(x1, y1, x2, y2, c);
    }
    // 二维前缀和
    for(int i = 1; i <= n; i++){
        for (int j =1; j <= m; j++){
           a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + b[i][j];
        }
    }
    for(int i = 1; i <= n; i++){
        for (int j =1; j <= m; j++){
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

可以参考这个原始的

用户头像
cjjj   2023-08-18 19:27         踩      回复

借个楼~
b[x1][ y1 ] +=c ;不因该是(x1,y1)到(x2+1,y2+1)都+c嘛

用户头像
cjjj   2023-08-18 19:46    回复了 cjjj 的评论         踩      回复

可以参考一维差分的最后计算,就是在不断的计算中,差分数组被不断更新,最后变为原数组的值吧

用户头像
ncust202103   2023-08-26 18:13      3    踩      回复

最后只要求输出变化后的值,所以不以a矩阵输出也可,即直接以b矩阵求自身前缀和的形式将b矩阵覆盖,和一般求前缀和矩阵方法一致。

用户头像
Wzzh   2023-09-04 22:43      14    踩      回复

从前往后求,可以覆盖的,在差分矩阵上直接操作就可以,不需要另开辟数组空间,就直接变成前缀和矩阵。
比如,另开辟专门的前缀和空间的话,假如s是前缀和,a是差分,如果求前缀和s应该是
s[i][j] = a[i][j] + s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1]
但是也可以直接在a上操作,不需要另辟空间s,如下式:
a[i][j] = a[i][j] + a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1]
右边旧的值a[i][j]是差分数组i,j处的值,新的a[i][j]的含义已经是前缀和了,直接用新的a[i][j]覆盖掉旧的a[i][j]
再用+=简化一下,就成了
a[i][j] += a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1]
前边求子矩阵前缀和那个题也是一样,可以不写s,直接把a原地覆盖为前缀和矩阵也可以。

用户头像
thebeatles   2023-09-22 23:06    回复了 Wzzh 的评论      3    踩      回复

你说的很对,我的理解:其实根本区别在于s是专门用来储存前缀和的,所以第一个式子很容易理解,至于第二个式子,a数组之所以难理解,是因为赋值过的a[i][j]储存的是前缀和,但后面没有修改没有操作的a[i][j]储存的还是差分数组的值,所以相当于省了空间而已

用户头像
无敌的拖拉机   9个月前    回复了 soar_fish 的评论         踩      回复

实际上就是用数组b保存了数组a的元素,也就是说通过b[i][j] = b[i][j - 1] + b[i - 1][j] + b[i][j] - b[i - 1][j - 1],b[i]被替换成a[i]

用户头像
acwing_85137   8个月前    回复了 Wzzh 的评论         踩      回复

太牛了,通透

用户头像
划过天际的流星雨   6个月前      1    踩      回复

其实,我觉得前面使用初始化差分数组的时候就用这个等式,把b[i][j]放到左边就行,最后再把a[i][j]还原,这样一切都顺理成章,Y总他们就是追求这种极简导致新手根本看不懂,而且会自以为讲得很清楚(笑哭)

用户头像
真的很想AK   10天前         踩      回复

真的很不友好,我在这卡了两个小时


用户头像
Barbed   2022-02-10 14:48      52    踩      回复

差分这样构建的原因:首先假设a,b都为空数组,也就是全部为0的情况,那么我们也可以说,b数组是a数组的差分数组!因为a[i][j] = b[1][1]+…b[i][j],因为都是0,所有情况满足!在这时a数组其实不为空,我们把a数组中的值看作(0+a[i][j])那么a数组的值变了,变成了a[i][j],这时如果b数组要想成为a数组的差分数组,值也要变为a[i][j],所以我们把b[i][j]变为a[i][j],这样就能满足b数组是a数组的差分数组。也就相当于想b数组中插入a[i][j].

用户头像
yrz_1   2022-02-22 03:25      12    踩      回复

👍🏻

用户头像
Barbed   2022-02-22 07:54    回复了 yrz_1 的评论      1    踩      回复

兄弟这么晚还在淦吗!强!

用户头像
百无禁忌_5   2022-04-27 22:23    回复了 Barbed 的评论         踩      回复

秒啊兄弟

用户头像
来时山有雪   2022-07-24 22:20         踩      回复

悟了!

用户头像
Fdu-Jaryn   2023-01-11 20:52         踩      回复

懂了,这样b就可以保持为a的差分数组

用户头像
hanhyojoo   2023-04-08 22:46         踩      回复

不懂

用户头像
Barbed   2023-04-09 15:00    回复了 hanhyojoo 的评论      1    踩      回复

多看几遍视频,多读几遍

用户头像
Dreamer_0   2023-11-03 18:26         踩      回复

nb

用户头像
云之君若雨   8个月前      1    踩      回复

终于懂了!

用户头像
ZhangJan   8个月前      1    踩      回复

转了好几圈,终于在老哥这里懂了

用户头像
放牛娃的蓝天   8个月前         踩      回复

牛逼

用户头像
Аη   4个月前      2    踩      回复

b[1][1]到b[i][j]矩形所有元素求和,最终得到b[i][j](值等同于a[i][j])是因为在insert操作中,某一个数b[l][k]参与计算后,无论朝右边还是下边计算,都会有一个-b[l][k]与之抵消,最终除了b[i][j](即a[i][j])外,其余全部被抵消为0


用户头像
在下令狐冲   2023-09-15 17:43      5    踩      回复

insert(i, j, i, j, a[i][j])是为了让b[i][j]这个位置上的元素增加a[i][j],同时从(1, 1)到(i, j)这一段的前缀和也增加到了a[i][j],如果使用两层for循环遍历整个b数组,则有:(1, 1)到(1, 1)的前缀和从0增加到了a[1][1],(1, 1)到(1, 2)的前缀和增加到了a[1][2]......,也就是相当于(i, j)位置的元素的前缀和全都变成了a[i][j],那么b数组自然变成了a数组的差分数组(根据差分数组的定义)。

用户头像
Unipuxin   2023-10-29 11:52         踩      回复

通透👍


用户头像
笨死了   2023-03-20 12:37      5    踩      回复

学习总结了一、二维前缀和差分,希望对你有帮助~
https://blog.csdn.net/m0_74215326/article/details/129620912?spm=1001.2014.3001.5502

用户头像
敲完这行就睡   9个月前      1    踩      回复

超级清楚orz


用户头像
bryant_Lin   2022-07-11 14:38      5    踩      回复

同一维差分的简化,简化掉一个数组

#include<iostream>
using namespace std;

const int N = 1010;

int n, m, q;
int b[N][N];

void insert(int x1, int y1, int x2, int y2, int c)
{
    b[x1][y1] += c;
    b[x1][y2+1] -= c;
    b[x2+1][y1] -= c;
    b[x2+1][y2+1] += c;
}

int main()
{
    cin >> n >> m >> q;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            int x;
            cin >> x;
            insert(i, j, i, j, x);
        }

    while(q--)
    {
        int x1, y1, x2, y2, c;
        cin >> x1 >> y1 >> x2 >> y2 >> c;
        insert(x1, y1, x2, y2, c);
    }

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1];
            cout << b[i][j] << " ";
        }
        cout << endl;
    }


    return 0;
}

用户头像
._742   2023-01-03 22:18      4    踩      回复

个人理解:insert的作用是使那一片区域内的值都加上c,而区域外面求和的话不受影响,那么当区域为一个点的时候,例如b[0][0]直接插入a[0][0]的值,那就使得这一个点的值从b[0][0]变成了a[0][0]的值,但是从b[0][1]处求和仍然是b[]0[1]=0,这样依次理解就行了


用户头像
南京李某的赘肉   9个月前      1    踩      回复

关于insert(i,j,i,j,A[i][j]):
假定A、B数组均为0,此时B为A的差分数组。
而A实际上是0向其中插入所有A[i][j]得到的。
并且:A数组中插入A[i][j]<=>B数组做insert(A[i][j])变换
当零数组A插入所有A[i][j]得到真正的A时,零数组B也做了所有对应的操作得到A的差分数组。


用户头像
粉色海洋   2023-06-16 20:31      1    踩      回复

每次看到鹿鹿的题解都感觉很详细,并且看完觉得很通透!希望鹿鹿把所有题解更完! 太爱鹿鹿了!


用户头像
lrs_0   2022-12-08 09:38      1    踩      回复

这个题为啥要求前缀和阿


用户头像
掘掘子来惹   2022-07-27 17:10      1    踩      回复

有没有其他方法构建差分数组啊,这个不理解呢

用户头像
Idlike_0   2022-07-28 17:58      9    踩      回复

a数组是b数组的前缀和,我们可以通过b数组得到a数组,插入实际上改变的是虚拟的a数组的值,也就是b数组的值,当虚拟的a数组建好,作为工具的b数组自然也完善好了。

用户头像
Shier833_Ww   2023-02-01 17:57    回复了 Idlike_0 的评论      2    踩      回复

!!你这么一说我就明白了!!一直以为那一步是在构建b[],想半天不知道什么道理,看完你说的才明白是通过构建一个虚拟a数组的过程中,顺便构建出了b[]!!感谢!!

用户头像
Casualer   2023-02-09 19:02    回复了 Shier833_Ww 的评论      1    踩      回复

xd,经过insert后,b数组和a数组不是一样了吗

用户头像
未央灬   2023-02-09 22:17    回复了 Casualer 的评论         踩      回复

底下的insert理解吗?理解的话这里的应该也理解啊。插入c要用insert,那么把a看作全零以后,依次插入a[i][j]复原的过程不也是相当于一次次insert

用户头像
Shier833_Ww   2023-02-09 23:50    回复了 Casualer 的评论      12    踩      回复

a数组是b数组的前缀和,而b数组是a数组的差分,对b数组中insert的操作真正的目的是通过改变b数组,而改变对应的a数组。

如果还是不大明白,你可以这样理解:
b数组一开始是0,所以b数组它所对应的前缀和c数组也是0(避免和题中的a数组混淆,我这里用c数组表示,c数组也就是上面ldlike_0同学说的虚拟的a数组)。
insert的操作过程是根据已有的a数组,将c数组复刻出一个一样的a数组。为了将c数组变成和a数组一样的数组,b数组也需要一直变化,因为只有b数组变了,它的前缀和c数组才能变。
最终由于b数组一直是c数组的差分数组,且c数组成为了和a数组一样,所以b数组也就是a数组的差分数组。这样不就构建出了a数组的差分数组了么~

你可以再想想~(我一开始也是跟你一样误解总想不明白,后来看看别人的解释,自己画画图才理解的)

用户头像
Blackgoat   2023-03-10 22:58    回复了 Shier833_Ww 的评论         踩      回复

我还是有点懵,所以b数组是原先的a数组加上每一个格子上的值还是什么

用户头像
Shier833_Ww   2023-03-12 20:52    回复了 Blackgoat 的评论         踩      回复

你的理解听起来是有点偏差的,a数组是b数组前缀和,怎么b数组会是原先a数组加上格子的值呢?

用户头像
未央灬   2023-03-17 00:08    回复了 Blackgoat 的评论         踩      回复

b是a的差分数组,a是b的前缀和

用户头像
acwing_85137   8个月前    回复了 Idlike_0 的评论      1    踩      回复

牛,突然就通透了


用户头像
shewasmydream   2022-06-02 20:55      1    踩      回复

偶遇群主,题解真详细,感谢


用户头像
evil_7   2022-05-15 12:30      1    踩      回复

为什么是这样构建差分数组呀for (int i = 1; i <= n; i)
{
for (int j = 1; j <= m; j
)
{
insert(i, j, i, j, a[i][j]); //构建差分数组
}
}
是把a的数传到b里面去吗

用户头像
普通朋友   2022-09-17 23:03      1    踩      回复

兄弟搞懂了吗,我这里也不太会

用户头像
相顾无言   8个月前         踩      回复

这样保证求和为就是原数组


用户头像
CodeWater   1个月前         踩      回复

我觉得二维差分前缀和那一部分的两种写法可以根据一维差分来进行推测:就比如一维差分的一种写法:
a[i]=a[i-1]+b[i];
就可以推测出二维差分的a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
b[i]+=b[i-1]则可以推测出b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
这样二维差分求前缀和的那一部分就会好理解一些


用户头像
MichaelCorleone   2个月前         踩      回复

完整的过程可以总结为以下三个步骤:

### 1. 初始化差分数组 b:
- 初始时,差分数组 b 是一个全为 0 的数组。接下来,我们要通过遍历矩阵 a,把 a 中的值体现在差分数组 b 上。

### 2. 用矩阵 a 初始化差分数组 b:
- 我们通过以下操作将矩阵 a 中的每个元素值转化到差分数组 b 中:
cpp for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { insert(i, j, i, j, a[i][j]); // 把每个 a[i][j] 的值插入到差分数组 b 中 } }
通过这种方式,差分数组 b 就记录了原始矩阵 a 的值。

### 3. 针对每个子矩阵插入 c:
- 根据输入的操作信息(x1, y1, x2, y2, c),在差分数组 b 中通过边界插入操作对指定的子矩阵进行增量修改。每次插入都在子矩阵的四个角进行增减操作,确保子矩阵区域的元素值增加 c,而其它部分不受影响。

例如,通过如下操作更新差分数组:
cpp insert(x1, y1, x2, y2, c);

### 4. 通过二维前缀和恢复矩阵的最终状态:
- 在差分数组 b 中完成了所有的修改后,接下来我们需要通过二维前缀和来将差分信息累加到矩阵的每个位置,恢复出最终矩阵。前缀和的计算公式是:
cpp b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];

通过这个公式,矩阵 b 中的每个位置会累积左、上和左上角的差分值,最终得到所有操作后的完整矩阵。

### 5. 输出最终结果:
- 计算完二维前缀和后,差分数组 b 就包含了经过所有操作后的矩阵值,最后我们输出矩阵 b 的结果。

### 总结:
- 初始化差分数组 b:差分数组初始为全 0。
- 用 a 填充 b:将原始矩阵 a 的值转化为差分数组 b。
- 插入操作 c:根据子矩阵边界在差分数组 b 中进行插入操作,调整子矩阵区域的值。
- 计算二维前缀和:通过前缀和公式累加差分,恢复最终矩阵的值。
- 输出结果:输出操作完成后的矩阵。

这样,经过上述过程,我们便可以高效地处理多个子矩阵区域的操作,并最终得到正确的结果。


用户头像
云遮月酒亦寒   7个月前         踩      回复

太厉害了


用户头像
卑傲   8个月前         踩      回复

#include[HTML_REMOVED]
#include[HTML_REMOVED]
#include[HTML_REMOVED]
#include[HTML_REMOVED]
using namespace std;
const int N=1010;
int n,m,q,c;
int s[N][N];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i)
{
for(int j=1;j<=m;j
)
{
scanf(“%d”,&s[i][j]);
}
}
while(q–)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2>>c;
for(int i=x1;i<=x2;i)
{
for(int j=y1;j<=y2;j
)
s[i][j]+=c;
}

}
   for(int i=1;i<=n;i++)
    {
    for(int j=1;j<=m;j++)
     printf("%d ",s[i][j]); 
     printf("\n");
    }
return 0;

}

用户头像
卑傲   8个月前         踩      回复

baoli


用户头像
外乡人   8个月前         踩      回复

神


用户头像
llwww   8个月前         踩      回复

#这个为什么是不对的?#
很奇怪的是5x5的测试矩阵它中间3x3的部分输出是正确的

#include<iostream>
using namespace std;
const int N = 10010;
long long arr[N][N], arr1[N][N];
int main()
{
    int n, m, q;
    cin >> n >> m >> q;
    //初始化矩阵
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)cin >> arr[i][j];
    //初始化差分矩阵
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            arr1[i][j] = arr[i][j] - arr[i][j - 1];
        }
    }
    //这里是对差分矩阵的操作
    for (int i = 1; i <= q; i++)//q是操作次数
    {
        int a, b, c, d, e;
        cin >> a >> b >> c >> d >> e;
        for (int f = b; f <= d; f++)//b,d是y轴
            arr1[f][a] += e, arr1[f][c+1] -= e;
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            arr1[i][j] += arr1[i][j - 1];
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cout << arr1[i][j] << " ";
        }
        cout << endl;
    }

}

用户头像
icekold   9个月前         踩      回复

我个人认为应该在矩阵+1和-1那里加上个空集的概念,这样方便理解,即[x2][y1]是我们这个矩阵数组还需要的部分,则它的下一个不需要的部分是[x2+1][y1]所以它为空集


用户头像
Alan_Lib   11个月前         踩      回复

AcWing《寒假每日一题2024》拼团优惠!https://www.acwing.com/activity/content/introduction/3684/group_buy/184900/


你确定删除吗?
1024
x

© 2018-2024 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息