【Soma do prefixo】【Diferença】|Soma do prefixo unidimensional|Soma do prefixo bidimensional|Diferença unidimensional|Diferença bidimensional|Explicação detalhada

Um, o prefixo e

1, prefixos e ideias

A soma do prefixo é uma ideia simples. Primeiro, tomamos a soma do prefixo unidimensional como exemplo. Ela é usada para resolver um intervalo rapidamente. Quando precisamos resolver um intervalo, é provável que o percorramos várias vezes, de modo que o time A complexidade atinge O(n) , mas quando esse algoritmo precisa ser consultado M vezes, nossa complexidade de tempo vai acelerar, então temos uma maneira simples de reduzir essa complexidade de tempo?

Quando resolvemos o intervalo [n, m] , podemos usar a ideia de a m +a m-1 +...+a n no algoritmo ingênuo para completar a solução ingênua desse intervalo. Agora queremos otimizá-lo Nesse processo, quando lemos o array, também podemos criar um array para encontrar as primeiras somas n. Usamos essa ferramenta de array e a ideia de S [m] - S [n] para completar o solução deste intervalo.
insira a descrição da imagem aqui

Então, vamos ver a soma de prefixos bidimensionais. A soma de prefixos bidimensionais é mais complicada do que a soma de prefixos unidimensionais. Também podemos imaginar a matriz bidimensional como uma matriz. Podemos resolver uma matriz de soma de prefixos para isso matriz. Este prefixo A forma de resolver a soma é uma ideia. Podemos ver na figura a seguir que queremos resolver a soma do prefixo da área A1 . Primeiro, precisamos usar a ideia de ​​​​A2 + A3 -A4 +D1 para resolvê-lo.D1 é o valor deste ponto. Desta forma, o processo de construção da matriz bidimensional pode ser concluído.
insira a descrição da imagem aquiDepois de concluído o processo de construção da matriz, como podemos resolver seu valor em uma determinada área?
insira a descrição da imagem aqui

Podemos usar esta operação de simulação para concluir o processamento da soma do prefixo bidimensional. Quando a soma do prefixo bidimensional é usada, precisamos apenas seguir a fórmula A1 + A2 -A3 -A4 para concluir a operação de cálculo logarítmico.

2. Implementação de código da soma do prefixo

A realização da soma do prefixo unidimensional: basta escrevê-la de acordo com a ideia do algoritmo acima e prestar atenção ao emitir, a operação desta saída é **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 ;
}

Soma de prefixo bidimensional: Uma coisa que precisamos prestar atenção é para evitar a ocorrência de problemas de array fora dos limites.Geralmente, iniciamos as operações de armazenamento do subscrito 1 em vez do subscrito 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 ;
}

Em segundo lugar, o algoritmo de diferença

1, ideia de algoritmo de diferença

O algoritmo de diferença é para resolver a operação do intervalo, e a soma do prefixo é para resolver a soma do intervalo. A chamada diferença é abrir uma matriz relacionada para armazenar a diferença entre este dígito e o dígito anterior, de modo a executar operações relacionadas . A primeira é a soma do prefixo unidimensional. Usamos apenas q[n] - q[n -1] para concluir a operação de armazenamento do array. Quando realizamos operações de intervalo e adicionamos x ao intervalo [n,m] , we A ideia é que c[n] += x , c[m + 1] -= x . Quando geramos essa matriz, podemos produzi-la adicionando passo a passo,

A matriz de diferença bidimensional é relativamente complicada. A diferença bidimensional não pode ser pensada como a soma bidimensional do prefixo. Pode-se dizer que esses dois são duas coisas com ideias diferentes. A matriz de diferença bidimensional é uma operação inversa . Primeiro, as duas fases As matrizes adicionadas são a[x1][y1] e **a[x2 + 1][y2 + 1]**, a operação de subtração é a operação de adicionar uma muito grande, podemos veja que o array a seguir é basicamente
insira a descrição da imagem aqui
um Ele interpreta perfeitamente a operação de diferença, o que explica a operação de leitura da matriz de diferença, mas não concluiu sua operação de saída, e sua operação de saída deve ser uma operação semelhante à soma do prefixo em ambos os lados e subtração na diagonal.

2. Realização do algoritmo de diferença

Algoritmo de diferença 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 diferença 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 ;
}

Três, o pensamento de dois algoritmos

Seja o algoritmo diferencial ou o algoritmo de soma de prefixos, todos eles se concentram em concluir a operação desse algoritmo por meio de uma ferramenta de matriz. Precisamos apenas dominar a criação dessas matrizes, o uso de intervalos e a operação de saída para concluir o compreensão desses algoritmos. Ao mesmo tempo, o prefixo A soma e a matriz da diferença são opostos, portanto, a criação da soma do prefixo é realmente equivalente à saída da diferença (versão avançada, para atribuir um valor à matriz da diferença) e a criação da diferença também é semelhante à saída da soma do prefixo (não exatamente a mesma)

Acho que você gosta

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