AcWing 798. Difference matrix [c++ detailed solution]

topic

Enter an integer matrix with n rows and m columns, and then enter q operations, each operation contains five integers x1, y1, x2, y2, c, where (x1, y1) and (x2, y2) represent the sub-matrix The coordinates of the upper left corner and the lower right corner.

Each operation must add c to the value of each element in the selected sub-matrix.

Please output the matrix after all operations are completed.
Input format

The first line contains integers n, m, q.

The next n rows, each row contains m integers, representing a matrix of integers.

Next line q, each line contains 5 integers x1, y1, x2, y2, c, representing an operation.
Output format

A total of n rows, each row of m integers, represents the final matrix after all operations are completed.
data range

1≤n, m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000,
−1000≤value of elements in matrix≤1000

Input sample:

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

Sample output:

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

2. Thinking

If it is extended to two dimensions, we need to add the value of each element in the selected submatrix of the two-dimensional array cto O(1)the time complexity that can also be achieved . The answer is yes, consider two-dimensional difference .

a[][]The array is b[][]the prefix of the array and the array, then it b[][]is a[][]the difference array

Original array: a[i][j]

We go to construct the difference array: b[i][j]

Make the aarray the sum of the rectangular elements enclosed by the upper left corner to the lower right corner a[i][j]of the barray .(1,1)(i,j)

How to construct ban array?

Unlike the one-dimensional difference, we can directly find a construction method to construct, so we can think in reverse .

For the same-dimensional difference, the purpose of constructing a two-dimensional difference array is to allow the aaddition cof each element in the selected neutron matrix in the original two-dimensional array to be O(n*n)optimized by the time complexityO(1)

Source array is known ain the selected sub-matrix is in (x1,y1)the upper left corner, in order (x2,y2)for the upper right corner of a rectangular region surrounded;

Always remember, a prefix and an array is an array of b array , such as on ban array of b[i][j]changes, will affect the aarray from a[i][j]each number and the next.

Assuming that we have constructed an barray, analogous to one-dimensional difference, we perform the following operations
to add the value of each element in the selected sub-matrixc

b[x1][y1] + = c;

b[x1,][y2+1] - = c;

b[x2+1][y1] - = c;

b[x2+1][y2+1] + = c;

bPerforming the above operations on the array each time is equivalent to:

for(int i=x1;i<=x2;i++)
  for(int j=y1;j<=y2;j++)
    a[i][j]+=c;

Let's draw a picture to understand this process:

b[x1][ y1 ] +=c; Corresponding to Figure 1, let the elements aof the blue rectangle area in the entire array are added c.
b[x1,][y2+1]-=c; Corresponding to Figure 2, let the elements aof the green rectangle area in the entire array be subtracted again c, so that the elements inside do not change.
b[x2+1][y1]- =c; Corresponding to Figure 3, let the elements aof the purple rectangle area in the entire array be subtracted again c, so that the elements inside do not change.
b[x2+1][y2+1]+=c; Corresponding to Figure 4, let the elements aof the red rectangle area in the entire array be added. The cred one is equivalent to being subtracted twice , and one more time ccan be restored.
Insert picture description here
We encapsulate the above operation into an insert function:

void insert(int x1,int y1,int x2,int y2,int c)
{
    
         //对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}

We can first imaginary aarray is empty, then the barray is also beginning to empty, but in fact athe array is not empty, so every time we make to (i,j)the upper left corner to with (i,j)a small box in the upper right corner for the area elements (in fact, the area) to insert c=a[i][j], equivalent to the original array ain (i,j)to (i,j)the range of plus a[i][j], thus performing n*minsertion, operation, successfully constructed a differential barray.

This is called saving the country by curve.

code show as below:

  for(int i=1;i<=n;i++)
  {
    
    
      for(int j=1;j<=m;j++)
      {
    
    
          insert(i,j,i,j,a[i][j]);    //构建差分数组
      }
  }

to sum up:

Insert picture description here

3. Code

include<iostream>
#include<cstdio>
using namespace std;
const int N=1e3+10;
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()
{
    
    
  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++)
      {
    
    
          b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
      }
  }
  for(int i=1;i<=n;i++)
  {
    
    
      for(int j=1;j<=m;j++)
      {
    
    
          printf("%d ",b[i][j]);
      }
      printf("\n");
  }
  return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45629285/article/details/111500293