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.
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.
Depois de concluído o processo de construção da matriz, como podemos resolver seu valor em uma determinada área?
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
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)