本文介绍: 二维差分
#include<bits/stdc++.h>

using namespace std;

const int N=1010;

int a[N][N],b[N][N],s[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++)
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+b[i][j];
            
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            cout<<s[i][j]<<" ";
        cout<<endl;
    }
    
    return 0;
}

二维差分

之前以为二维前缀和全是公式,其实公式是有其实际意义的,所以也不全是死记硬背

现在回想一下那个公式,其实自己也是可以现场推导出来的,公式的意思是,s数组表示该点及其左上角所有点的和

给定我们一个矩阵左上角的顶点和右下角的顶点,我们要求这个矩阵内的所有点的和,使用二维前缀和,假设左上角的点的坐标是

(

x

1

,

y

1

)

(x_1,y_1)

(x1,y1),右下角的坐标是

(

x

2

,

y

2

)

(x_2,y_2)

(x2,y2),画格子来进行理解即可理解该公式的实际意义

ans=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1],最后加上的部分是被多减了一次,所以补回来

二维差分和一维差分是一样的,还是定义一个插入函数,差分的逆运算是前缀和,对差分数组b数组进行操作,相当于对该点右下角的所有元素都进行了该操作,所以要实现某一个矩阵内的修改,只需要对左上角和右下角的顶点进行修改,但是,会出现有一些部分多减,所以需要在最后加回来,和二维前缀和一样,用画格子来进行理解是最方便的

插入函数如下

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

如何构造差分数组呢

可以首先把a数组看成是空数组,或者说全是0的数组,那么b数组自然就是a数组的差分数组了,然后调用插入函数,相当于在一个一乘一的矩阵上插入a数组的每一个元素,插入完成之后就构建好了b数组

上面这个比较绕,建议是多思考一下

然后就是插入元素,求b数组的前缀和,输出前缀和,前缀和就是修改后的答案数组

原文地址:https://blog.csdn.net/L3102250566/article/details/136047668

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_68385.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注