差分矩阵(二维差分)

一、算法描述

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

含义

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

怎么求

  • 跟一维一样,插入一遍即可,但是要注意每次插入要在同一个位置内插入,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  阅读(1896)  评论(0)    收藏  举报