Algorithm's prefix sum and difference code implementation and algorithm thinking analysis

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 ≤1000

Input 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≤1000

Input 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 ≤1000

Input 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≤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

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

 

Guess you like

Origin blog.csdn.net/JixTlhh/article/details/115254947