算法笔记——二维矩阵的差分

294 阅读2分钟

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

什么是二维矩阵的差分

二维矩阵的差分是二维矩阵前缀和的逆运算,那什么是二维矩阵的前缀和呢,可以参考这篇文章算法笔记——前缀和 - 掘金 (juejin.cn)

二维矩阵差分的公式

知道定义后就不难推出其中蕴含哲理行的公式了:

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c: S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

一般差分会搭配二维矩阵的前缀和公式来使用:

s[x1,y1]+=s[x1-1,y1]+s[x1,y1-1]-s[x1-1,y1-1]

有了二维矩阵的差分就不用多次循环去进行元素的叠加,直接利用差分的性质就可以很轻松的得出答案。

具体题目信息

题目描述

在 n×n 的格子上有 m个地毯。

给出这些地毯的信息,问每个点被多少个地毯覆盖。

输入格式

第一行,两个正整数 n,m。意义如题所述。

接下来 mm行,每行两个坐标 (x1,y1)(x1,y1) 和 (x2,y2)(x2,y2),代表一块地毯,左上角是 (x1,y1)(x1,y1),右下角是 (x2,y2)(x2,y2)。

输出格式

输出 n 行,每行 n个正整数。

第 i 行第 j列的正整数表示 (i,j) 这个格子被多少个地毯覆盖。

输入输出样例

输入 #1复制

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

输出 #1复制

0 1 1 1 0
0 1 1 0 0
0 1 2 1 1
0 0 1 1 1
0 0 1 1 1

代码:

#include<iostream>
#include<stdio.h>
using namespace std;
​
const int N=1010;
int 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;
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            
            b[i][j]=0;
        }
    }
    
    while(m--){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        insert(x1,y1,x2,y2,1);
    }
    
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;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;
}
​

\