table of Contents
One-dimensional case of prefix sum
Two-dimensional case of prefix sum
The one-dimensional case of difference
The two-dimensional case of difference
What is the prefix sum?
One-dimensional case of prefix sum
We define two arrays, the original array a[] and the prefix and the array S[]
Original array: a1, a2, a3...an
We say S1=a1, S2=a1+a2, S3=a1+a2+a3
It is not difficult to find the rule, the prefix sum can be obtained as Si=a1+a2+……+ai; Si=Si-1 + ai;
Then there are two problems :
1. How to find Si
2. What are the prefixes and Si used for, and what are their functions?
We define S0=0
The code implementation prefix sum is as follows:
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + a[i];
}
Now let’s expand a bit and find the sum on the interval [l,r] (l stands for left, r stands for right)
Then the sum of this paragraph is: Sr-Sl-1
As shown in the figure, this method can reduce the time complexity to O(1);
Let's look at a question:
Enter a sequence of integers of length n.
Next, enter m queries, and enter a pair of l,r for each query.
For each query, output the sum from the lth number to the rth number in the original sequence.
Input format
The first line contains two integers n and m.
The second line contains n integers, representing a sequence of integers.
The next m lines, each line contains two integers l and r, representing a range of the query interval.
Output format
There are m rows in total, and each row outputs one query result.
data range
1≤l≤r≤n
1≤n,m≤100000
−1000≤The value of the element in the sequence ≤1000Input sample:
5 3 2 1 3 6 4 1 2 1 3 2 4
Sample output :
3 6 10
The code is implemented as follows:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N], s[N];
int n, m;
int main()
{
s[0] = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + a[i];//前缀和公式
}
while (m--)
{
int l, r;
cin >> l >> r;
printf("%d\n", s[r] - s[l - 1]);//区间和公式
}
return 0;
}
Two-dimensional case of prefix sum
//二维前缀和
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] + a[i][j];
}
}
Let's look at a topic:
Enter an integer matrix with n rows and m columns, and then enter q queries. Each query contains four integers x1, y1, x2, y2, which represent the coordinates of the upper left corner and the lower right corner of a sub-matrix.
For each query, the sum of all numbers in the sub-matrix is output.
Input format
The first line contains three integers n, m, q
The next n rows, each row contains m integers, representing a matrix of integers.
Next q lines, each line contains four integers x1, y1, x2, y2 representing a set of queries.
Output format
There are q lines in total, and each line outputs a query result.
data range
1≤n,m≤1000
1≤q≤200000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤value of element in matrix≤1000Input sample :
3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4
Sample output :
17 27 21
The code is implemented as follows:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N][N], s[N][N];
int n, m;
int q;
int main()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
}
}
while (q--)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
printf("%d\n", s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]);
}
return 0;
}
The one-dimensional case of difference
Let's look at a question:
Enter a sequence of integers of length n.
Next, enter m operations, each operation contains three integers l,r,c, which means adding c to each number between [l,r] in the sequence.
Please output the sequence after all operations have been performed.
Input format
The first line contains two integers n and m.
The second line contains n integers, representing a sequence of integers.
Next m lines, each line contains three integers l, r, c representing an operation.
Output format
A line containing n integers represents the final sequence.
data range
1≤n,m≤100000
1≤l≤r≤n
−1000≤c≤1000
−1000≤The value of the element in the integer sequence ≤1000Input sample :
6 3 1 2 2 1 2 1 1 3 1 3 5 1 1 6 1
Sample output:
3 4 5 3 4 2
Think about how to add a c to each number in the interval [l,r]
We can do this:
Divide the interval [l, r] into q sub-intervals
In the interval [l,l] a[l]+c In the interval [l+1,l+1] a[l+1]+c……In the area [r,r] a[r]+c ;
The complete code is as follows:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int a[N], b[N];
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; i++)
insert(i, i, a[i]);
while (m--)
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
insert(l, r, c);
}
for (int i = 1; i <= n; i++)
b[i] += b[i - 1];
for (int i = 1; i <= n; i++)
{
printf("%d ", b[i]);
}
return 0;
}
The two-dimensional case of difference
One-dimensional situation is to add a value to an interval
In the two-dimensional case, add a value to a sub-matrix
Let's look at a question:
Input an integer matrix with n rows and m columns, and then input q operations, each operation contains five integers x1, y1, x2, y2, c where (x1, y1) and (x2, y2) represent the upper left of a sub-matrix The corner coordinates and the lower right corner coordinates.
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 q lines, each line contains 5 integers x1, y1, x2, y2, c represents an operation.
Output format
A total of n rows, m integers in each row, represent 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≤1000Input 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
The code is implemented as follows:
#include <bits/stdc++.h>
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()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &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;
scanf("%d%d%d%d%d", &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;
}