Implementación de código de suma y diferencia de prefijo de algoritmo y análisis de pensamiento de algoritmo

Tabla de contenido

Caso unidimensional de suma de prefijo

Caso bidimensional de suma de prefijo

El caso unidimensional de la diferencia

El caso bidimensional de la diferencia


¿Cuál es la suma del prefijo?

Caso unidimensional de suma de prefijo

Definimos dos matrices, la matriz original a [] y el prefijo y la matriz S []

Matriz original: a1, a2, a3 ... an

Decimos S1 = a1, S2 = a1 + a2, S3 = a1 + a2 + a3

No es difícil encontrar la regla, la suma del prefijo se puede obtener como Si = a1 + a2 + …… + ai; Si = Si-1 + ai;

Entonces hay dos problemas :

1. Cómo encontrar Si

2. ¿Para qué se utilizan los prefijos y Si, y cuáles son sus funciones?

Definimos S0 = 0

La suma del prefijo de implementación del código es la siguiente:

for (int i = 1; i <= n; i++)
{
	s[i] = s[i - 1] + a[i];
}

Ahora expandamos un poco y encontremos la suma en el intervalo [l, r] (l significa izquierda, r significa derecha)

Entonces la suma de este párrafo es: Sr-Sl-1

Como se muestra en la figura, este método puede reducir la complejidad del tiempo a O (1);

 

Veamos una pregunta:

Introduzca una secuencia de números enteros de longitud n.

A continuación, ingrese m consultas e ingrese un par de l, r para cada consulta.

Para cada consulta, genere la suma desde el número 1 hasta el número 6 en la secuencia original.

Formato de entrada

La primera línea contiene dos números enteros n y m.

La segunda línea contiene n números enteros, que representan una secuencia de números enteros.

Las siguientes m líneas, cada línea contiene dos números enteros lyr, que representan un rango del intervalo de consulta.

Formato de salida

Hay m filas en total y cada fila genera un resultado de consulta.

rango de datos

1≤l≤r≤n  
1≤n, m≤100000
−1000≤El valor del elemento en la secuencia ≤1000

Muestra de entrada:

5 3
2 1 3 6 4
1 2
1 3
2 4

Salida de muestra :

3
6
10

 El código se implementa de la siguiente manera:

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

Caso bidimensional de suma de prefijo

//二维前缀和
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];
	}
}

Veamos un tema:

Ingrese una matriz entera con n filas ym columnas, y luego ingrese q consultas. Cada consulta contiene cuatro enteros x1, y1, x2, y2, que representan las coordenadas de la esquina superior izquierda y la esquina inferior derecha de una submatriz.

Para cada consulta, se genera la suma de todos los números de la submatriz.

Formato de entrada

La primera línea contiene tres números enteros n, m, q

Las siguientes n filas, cada fila contiene m enteros, que representan una matriz de enteros.

A continuación, q líneas, cada línea contiene cuatro números enteros x1, y1, x2, y2 que representan un conjunto de consultas.

Formato de salida

Hay q líneas en total y cada línea genera un resultado de consulta.

rango de datos

1≤n, m≤1000
1≤q≤200000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤valor del elemento en la matriz≤1000

Muestra de entrada :

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

Salida de muestra :

17
27
21

El código se implementa de la siguiente manera: 

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

El caso unidimensional de la diferencia

Veamos una pregunta:

Introduzca una secuencia de números enteros de longitud n.

Luego, ingrese m operaciones, cada operación contiene tres enteros l, r, c, lo que significa sumar c a cada número entre [l, r] en la secuencia.

Imprima la secuencia después de que se hayan realizado todas las operaciones.

Formato de entrada

La primera línea contiene dos números enteros n y m.

La segunda línea contiene n números enteros, que representan una secuencia de números enteros.

Las siguientes m líneas, cada línea contiene tres enteros l, r, c que representan una operación.

Formato de salida

Una línea que contiene n números enteros representa la secuencia final.

rango de datos

1≤n, m≤100000
1≤l≤r≤n
−1000≤c≤1000
−1000≤ El valor del elemento en la secuencia entera ≤1000

Muestra de entrada :

6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1

Salida de muestra:

3 4 5 3 4 2

Piense en cómo sumar una c a cada número en el intervalo [l, r]

Podemos hacer esto:

Divida el intervalo [l, r] en q subintervalos

En el intervalo [l, l] a [l] + c En el intervalo [l + 1, l + 1] a [l + 1] + c …… En el área [r, r] a [r] + c ;

El código completo es el siguiente:

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

El caso bidimensional de la diferencia

Situación unidimensional es agregar un valor a un intervalo

En el caso bidimensional, agregue un valor a una submatriz

Veamos una pregunta:

Ingrese una matriz de enteros con n filas ym columnas, y luego ingrese q operaciones, cada operación contiene cinco enteros x1, y1, x2, y2, c donde (x1, y1) y (x2, y2) representan la parte superior izquierda de un sub -matriz Las coordenadas de la esquina y las coordenadas de la esquina inferior derecha.

Cada operación debe sumar c al valor de cada elemento en la submatriz seleccionada

Genere la matriz después de que se hayan completado todas las operaciones.

Formato de entrada

La primera línea contiene números enteros n, m, q

Las siguientes n filas, cada fila contiene m enteros, que representan una matriz de enteros.

A continuación q líneas, cada línea contiene 5 enteros x1, y1, x2, y2, c representa una operación.

Formato de salida

Un total de n filas, m enteros en cada fila, representan la matriz final después de completar todas las operaciones.

rango de datos

1≤n, m≤1000
1≤q≤100000
1≤x1≤x2≤n
1≤y1≤y2≤m
−1000≤c≤1000
−1000≤valor del elemento en la matriz≤1000

Muestra de entrada:

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

Salida de muestra:

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

 El código se implementa de la siguiente manera:

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

 

Supongo que te gusta

Origin blog.csdn.net/JixTlhh/article/details/115254947
Recomendado
Clasificación