差分矩阵(二维差分)

一、算法描述

上一篇文章介绍了一维差分,本篇文章来介绍一下什么是二维差分。

含义

  • 显然一维差分是一维前缀和的原数组,那么二维差分就是二维前缀和的原数组。

怎么求

  • 跟一维一样,插入一遍即可,但是要注意每次插入要在同一个位置内插入,insert(i, j, i, j, a[i][j]);

怎么用

  • 一维差分是使得数组 \(a[n]\)\([l, r]\) 范围内的数都加上 \(c\) ,那么二维差分的作用就是使得 \(a[n][n]\)\((x1, y1)\)\((x2, y2)\) 范围内的数都加上 \(c\)

  • 差分操作的都是原数组 \(b\) ,通过 \(b\) 求一遍前缀和才能得到 \(a\) ,也要注意我们操作的都是差分数组 \(b\) ,那么我们如何操作 \(b\) 才能得到上面的效果呢?

  • 首先b[x1][y1] += c;,这样就会使得 \((x1, y1)\) 到右下角所有的数都加上 \(c\) ,然后有一些是不需要加但是加了的,所以要减回来,b[x2 + 1][y1] -= c, b[x1][y2 + 1] -= c;,这样操作之后右下角有一块减了两次,所以还要再加回来一次,b[x2 + 1][y2 + 1] += c;,这样就可以达到效果了,建议读者在草稿纸上画一下,更好理解。

代码如下:

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;
}

二、题目描述

输入一个 \(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,\)
\(1≤x1≤x2≤n,\)
\(1≤y1≤y2≤m,\)
\(−1000≤c≤1000,\)
\(−1000≤矩阵内元素的值≤1000\)

输入样例:

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

输出样例:

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

三、题目来源

AcWing算法基础课-798.差分矩阵

四、源代码

#include <iostream>

using namespace std;

const int N = 1010;

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()
{
    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)
            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)    cout << a[i][j] << ' ';
        cout << endl;
    }
    
    return 0;
}
posted @ 2023-10-20 19:05  grave-master  阅读(127)  评论(0编辑  收藏  举报