2020/9/30 Acwing-差分数组矩阵

差分数组矩阵

题目

输入一个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

题目分析

对差分数组的理解:差分数组的前缀和其实就是原数组.了解这个即可.那么我们直接把原数组看做前缀和即可.
知道原数组其实就是前缀和,那就很容易推出s(a,b)(指差分数组)的值=l(a,b)-l(a,b-1)-l(a-1,b)+l(a-1.b-1).
图示为如何理解前缀数组在差分数组中表示的含义
同一维一样,求差分数组的原因是因为,所有对原数组的区域加值操作都能转化为对差分数组的某些点的加值操作.当我们在差分数组中对应的记录下这些操作,想要求原数组的变化,只需要用前缀和的方法就可以得到答案.

而且类似的,我们先将两个全为0的数组分别作为差分数组和前缀和数组,然后,依次对前缀和数组做区域插值操作(所谓区域其实在这里就是一个点),这样,当把所有的值都插在了对应的位置上,差分数组就记录下了所有这些操作.再然后,我们通过输入再度在前缀和矩阵进行区域加值,同样的,也都会忠实的记录在差分数组中.也就是说,此时的差分数组,已经记录下了前缀和数组从 全0状态–>初始数组状态–>进行数次操作后的状态,这所有的操作,想要知道现在的前缀和数组什么样,只需要通过差分数组就知道了—>对差分数组做求前缀和的操作即可.

源代码

import java.util.Scanner;
class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int q=sc.nextInt();
        int[][] dif=new int[1010][1010];

        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
            {int x=sc.nextInt();
            insert(dif,i,j,i,j,x);}
        }
        while(q-->0){
            int x1=sc.nextInt();
            int y1=sc.nextInt();
            int x2=sc.nextInt();
            int y2=sc.nextInt();
            int c=sc.nextInt();
            insert(dif,x1,y1,x2,y2,c);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dif[i][j]+=dif[i-1][j]+dif[i][j-1]-dif[i-1][j-1];
                System.out.print(dif[i][j]+" ");
            }
            System.out.println();
        }
    }
    //解释下是如何将对前缀和数组的操作映射到差分数组上的
    //差分数组某点上加一个数,会使得前缀和数组右下所有值都加c(因为这些点要求前缀和都要加上这个+c的数)
    static void insert(int[][] d,int x1,int y1,int x2,int y2,int c){//函数功能:把对原数组的操作 存储在差分数组中
        d[x1][y2+1]-=c;
        d[x2+1][y1]-=c;
        d[x2+1][y2+1]+=c;
        d[x1][y1]+=c;
    }
}

值得一提的是,在将差分数组变为前缀和数组的时候,并没有新建一个数组,而是直接将原数组的值进行依次的更新,直接遍历过的点表示前缀和,这样可以使代码更加简洁.
当然也可以新建一个前缀和数组,里边的数都表示前缀和,这样会更清晰点.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值