【Suma de prefijo】【Diferencia】|Suma de prefijo unidimensional|Suma de prefijo bidimensional|Diferencia unidimensional|Diferencia bidimensional|Explicación detallada

Uno, el prefijo y

1, prefijos e ideas

El prefijo suma es una idea simple. Primero, tomamos el prefijo suma unidimensional como ejemplo. Se usa para resolver rápidamente un intervalo. Cuando necesitamos resolver un intervalo, es probable que lo atraviesemos varias veces, de modo que el time La complejidad alcanza O(n) , pero cuando este algoritmo necesita ser consultado M veces, nuestra complejidad de tiempo se acelerará, entonces, ¿tenemos una manera simple de reducir esta complejidad de tiempo?

Cuando resolvemos el intervalo [n, m] , podemos usar la idea de a m +a m-1 +...+a n en el algoritmo ingenuo para completar la solución ingenua a este intervalo. Ahora queremos optimizarlo En este proceso, cuando leemos la matriz, también podemos crear una matriz para encontrar las primeras n sumas. Usamos esta herramienta de matriz y la idea de S [m] - S [n] para completar la solución de este intervalo.
inserte la descripción de la imagen aquí

Entonces veamos la suma de prefijos bidimensional. La suma de prefijos bidimensional es más complicada que la suma de prefijos unidimensional. También podemos imaginar la matriz bidimensional como una matriz. Podemos resolver una matriz de suma de prefijos para esto matriz. Este prefijo La forma de resolver la suma es una idea. Podemos ver en la siguiente figura que queremos resolver el prefijo suma del área A1 . Primero, necesitamos usar la idea de A2 + A3 -A4 +D1 para resolverlo.D1 es el valor de este punto. De esta manera, se puede completar el proceso de construcción de la matriz bidimensional.Después
inserte la descripción de la imagen aquíde completar el proceso de construcción de la matriz, ¿cómo podemos resolver su valor en un área determinada?
inserte la descripción de la imagen aquí

Podemos usar esta operación de simulación para completar el procesamiento de la suma de prefijos bidimensionales. Cuando se usa la suma de prefijos bidimensionales, solo necesitamos seguir la fórmula A1 + A2 -A3 -A4 para completar la operación de cálculo logarítmico.

2. Implementación de código de suma de prefijo

La realización de la suma de prefijos unidimensionales: simplemente escríbalo de acuerdo con la idea del algoritmo anterior y preste atención al generar, la operación de esta salida es ** S [x] - S [y - 1] ** operar.

#include <iostream>
using namespace std ;
const int N = 100010 ;

int q[N] , s[N] ;
//存储该点的数值的q[N]数组,存储前缀和的s[N]数组
int main ()
{
    
    
    int n , m ;
    cin >> n >> m ;
    for(int i = 1 ; i <= n ; i ++ )
    {
    
    
        cin >> q[i] ;
        s[i] = s[i - 1] + q[i] ;
    }
    //完成两个数组的建立
    while ( m -- )
    {
    
    
        int x , y ;
        cin >> x >> y ;
        cout << s[y] - s[x - 1] << endl; 
    }
    return 0 ;
}

Suma de prefijo bidimensional: una cosa a la que debemos prestar atención es para evitar que se produzcan problemas fuera de los límites de la matriz. Generalmente, comenzamos las operaciones de almacenamiento desde el subíndice 1 en lugar del subíndice 0 .

#include <iostream>
using namespace std ;

const int N = 1010 ;

int q[N][N] , s[N][N] ;


int main ()
{
    
    ios::sync_with_stdio(0);
    int n , m , cnt ;
    cin >> n >> m >> cnt ;
    for(int i = 1 ; i <= n ; i ++ )
        for(int j = 1 ;j <=m ;j ++ )
            cin >> q[i][j] ;
//完成q数组的构建
        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] + q[i][j] - s[i - 1][j - 1] ;
//完成s数组的构建
        while (cnt -- )
            {
    
    
                int x1, x2, y1 , y2 ;
                cin >> x1 >> y1 >> x2 >> y2 ;
                cout << s[x1 - 1][y1 - 1] + s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] << endl ; 
            }

    return 0 ;
}

En segundo lugar, el algoritmo de diferencia

1, idea de algoritmo de diferencia

El algoritmo de diferencia es para resolver la operación de intervalo, y la suma de prefijos es para resolver la suma de intervalo. La llamada diferencia es abrir una matriz relacionada para almacenar la diferencia entre este dígito y el dígito anterior, a fin de realizar operaciones relacionadas. . La primera es la suma de prefijos unidimensionales. Solo usamos q[n] - q[n -1] para completar la operación de almacenamiento de la matriz. Cuando realizamos operaciones de intervalo y sumamos x al intervalo [n,m] , we La idea es que c[n] += x , c[m + 1] -= x . Cuando generamos esta matriz, podemos generarla agregando paso a paso,

La matriz de diferencias bidimensionales es relativamente complicada. La diferencia bidimensional no se puede considerar como la suma de prefijos bidimensionales. Se puede decir que estos dos son dos cosas con ideas diferentes. La matriz de diferencias bidimensionales es una operación hacia atrás. Primero, las dos fases Las matrices a sumar son a[x1][y1] y **a[x2 + 1][y2 + 1]**, la operación de resta es la operación de sumar al máximo, nosotros puede ver que la siguiente matriz se considera básicamente
inserte la descripción de la imagen aquí
como Interpreta perfectamente la operación de diferencia, lo que explica la operación de lectura de la matriz de diferencia, pero no ha completado su operación de salida, y su operación de salida debería ser una operación similar al prefijo suma en ambos lados y resta en la diagonal.

2. Realización del algoritmo de diferencia.

Algoritmo de diferencia unidimensional

#include <iostream>
using namespace std ;

const int N  =100010 ;

int q[N] , k[N] ;

int main ()
{
    
    
    int n , m ;
    cin >> n >> m;
    for(int i = 1 ; i <= n ;i ++ )
    {
    
    
        cin >> q[i] ;
        k[i] = q[i] - q[i - 1] ;
    }

    //完成原数组和差分数组的赋值操作
    while ( m -- )
    {
    
    
        int x ,y , z ;
        cin >> x  >> y >> z;
        //核心步骤
        k[x] +=z ;
        k[y + 1] -= z ;
        //以上两步
    }
    int cnt = 0 ;
    for(int i = 1 ; i <= n ; i ++ )
        {
    
    
            cnt +=k[i];
            cout << cnt << " ";
        }
    return 0 ;
}

Algoritmo de diferencia 2D

#include <iostream>

using namespace std ;

const int N = 1010 ;

int q[N][N] , k[N][N] ;

void insert (int x1 ,int y1 ,int x2 ,int y2 ,int z)
{
    
    
    k[x1][y1] += z; 
    k[x2 + 1][y2 + 1] += z ;
    k[x2 + 1][y1] -= z ;
    k[x1][y2 + 1] -= z ; 
}

int main ()
{
    
    
    int n , m , p ;
    cin >> n >> m >> p;
    for(int i = 1 ; i <= n ; i ++ )
        for(int j = 1 ; j <= m ; j ++ )
            {
    
    cin >> q[i][j] ;
            insert(i , j , i , j,q[i][j]);
            }
        while (p --)
        {
    
    
            int x1 ,y1, x2 ,y2 ,cnt ;
            cin >> x1 >> y1 >> x2 >> y2 >> cnt ;
            insert(x1 ,y1 ,x2 ,y2 ,cnt );
        }
        for(int i = 1 ;i <= n ;i ++ )
           {
    
     for(int j = 1 ;j <= m ;j ++ )
            {
    
    
                k[i][j] +=  k[i - 1][j] + k[i][j - 1]- k[i -1 ][j - 1];
                cout << k[i][j] << " ";
            }
            cout << endl; 
        }
    return 0 ;
}

Tres, el pensamiento de dos algoritmos.

Ya sea el algoritmo diferencial o el algoritmo de suma de prefijos, todos se enfocan en completar la operación de este algoritmo a través de una herramienta de matriz, solo necesitamos dominar la creación de estas matrices, el uso de intervalos y la operación de salida para completar el comprensión de estos algoritmos Al mismo tiempo, el prefijo La matriz de suma y diferencia son opuestos, por lo que la creación del prefijo suma es en realidad equivalente a la salida de la diferencia (versión avanzada, para asignar un valor a la matriz de diferencia) y la creación de la diferencia también es similar a la salida de la suma del prefijo (no exactamente igual)

Supongo que te gusta

Origin blog.csdn.net/wen030803/article/details/131717200
Recomendado
Clasificación