Consultas de suma de subarray

Dada una array de tamaño M x N, hay un gran número de consultas para encontrar sumas de subarrays. Las entradas a las consultas son los índices superior izquierdo e inferior derecho de la subarray cuya suma es averiguar. 
Cómo preprocesar la array para que las consultas de suma de subarray se puedan realizar en tiempo O(1).
Ejemplo : 
 

tli :  Row number of top left of query submatrix
tlj :  Column number of top left of query submatrix
rbi :  Row number of bottom right of query submatrix
rbj :  Column number of bottom right of query submatrix

Input: mat[M][N] = {{1, 2, 3, 4, 6},
                    {5, 3, 8, 1, 2},
                    {4, 6, 7, 5, 5},
                    {2, 4, 8, 9, 4} };
Query1: tli = 0, tlj = 0, rbi = 1, rbj = 1
Query2: tli = 2, tlj = 2, rbi = 3, rbj = 4
Query3: tli = 1, tlj = 2, rbi = 3, rbj = 3;

Output:
Query1: 11  // Sum between (0, 0) and (1, 1)
Query2: 38  // Sum between (2, 2) and (3, 4)
Query3: 38  // Sum between (1, 2) and (3, 3)

Le recomendamos encarecidamente que minimice su navegador y que pruebe esto usted mismo primero.
La idea es crear primero una array auxiliar aux[M][N] tal que aux[i][j] almacene la suma de elementos en la subarray desde (0,0) hasta (i,j). Una vez que se construye aux[][], podemos calcular la suma de la subarray entre (tli, tlj) y (rbi, rbj) en tiempo O(1). Necesitamos considerar aux[rbi][rbj] y restar todos los elementos innecesarios. A continuación se muestra la expresión completa para calcular la suma de la subarray en tiempo O(1).
 

C++

// C++ program to compute submatrix query sum in O(1)
// time
#include<iostream>
using namespace std;
#define M 4
#define N 5
 
// Function to preprocess input mat[M][N].  This function
// mainly fills aux[M][N] such that aux[i][j] stores sum
// of elements from (0,0) to (i,j)
int preProcess(int mat[M][N], int aux[M][N])
{
   // Copy first row of mat[][] to aux[][]
   for (int i=0; i<N; i++)
      aux[0][i] = mat[0][i];
 
   // Do column wise sum
   for (int i=1; i<M; i++)
      for (int j=0; j<N; j++)
         aux[i][j] = mat[i][j] + aux[i-1][j];
 
   // Do row wise sum
   for (int i=0; i<M; i++)
      for (int j=1; j<N; j++)
         aux[i][j] += aux[i][j-1];
}
 
// A O(1) time function to compute sum of submatrix
// between (tli, tlj) and (rbi, rbj) using aux[][]
// which is built by the preprocess function
int sumQuery(int aux[M][N], int tli, int tlj, int rbi,
                                              int rbj)
{
    // result is now sum of elements between (0, 0) and
    // (rbi, rbj)
    int res = aux[rbi][rbj];
 
    // Remove elements between (0, 0) and (tli-1, rbj)
    if (tli > 0)
       res = res - aux[tli-1][rbj];
 
    // Remove elements between (0, 0) and (rbi, tlj-1)
    if (tlj > 0)
       res = res - aux[rbi][tlj-1];
 
    // Add aux[tli-1][tlj-1] as elements between (0, 0)
    // and (tli-1, tlj-1) are subtracted twice
    if (tli > 0 && tlj > 0)
       res = res + aux[tli-1][tlj-1];
 
    return res;
}
 
// Driver program
int main()
{
   int mat[M][N] = {{1, 2, 3, 4, 6},
                    {5, 3, 8, 1, 2},
                    {4, 6, 7, 5, 5},
                    {2, 4, 8, 9, 4} };
   int aux[M][N];
 
   preProcess(mat, aux);
 
   int tli = 2, tlj = 2, rbi = 3, rbj = 4;
   cout << "\nQuery1: " << sumQuery(aux, tli, tlj, rbi, rbj);
 
   tli = 0, tlj = 0, rbi = 1, rbj = 1;
   cout << "\nQuery2: " << sumQuery(aux, tli, tlj, rbi, rbj);
 
   tli = 1, tlj = 2, rbi = 3, rbj = 3;
   cout << "\nQuery3: " << sumQuery(aux, tli, tlj, rbi, rbj);
 
   return 0;
}

Java

// Java program to compute submatrix query
// sum in O(1) time
class GFG {
     
    static final int M = 4;
    static final int N = 5;
     
    // Function to preprocess input mat[M][N].
    // This function mainly fills aux[M][N]
    // such that aux[i][j] stores sum of
    // elements from (0,0) to (i,j)
    static int preProcess(int mat[][], int aux[][])
    {
         
        // Copy first row of mat[][] to aux[][]
        for (int i = 0; i < N; i++)
            aux[0][i] = mat[0][i];
         
        // Do column wise sum
        for (int i = 1; i < M; i++)
            for (int j = 0; j < N; j++)
                aux[i][j] = mat[i][j] +
                                aux[i-1][j];
         
        // Do row wise sum
        for (int i = 0; i < M; i++)
            for (int j = 1; j < N; j++)
                aux[i][j] += aux[i][j-1];
                 
        return 0;
    }
     
    // A O(1) time function to compute sum
    // of submatrix between (tli, tlj) and
    // (rbi, rbj) using aux[][] which is
    // built by the preprocess function
    static int sumQuery(int aux[][], int tli,
                    int tlj, int rbi, int rbj)
    {
         
        // result is now sum of elements
        // between (0, 0) and (rbi, rbj)
        int res = aux[rbi][rbj];
     
        // Remove elements between (0, 0)
        // and (tli-1, rbj)
        if (tli > 0)
            res = res - aux[tli-1][rbj];
     
        // Remove elements between (0, 0)
        // and (rbi, tlj-1)
        if (tlj > 0)
            res = res - aux[rbi][tlj-1];
     
        // Add aux[tli-1][tlj-1] as elements
        // between (0, 0) and (tli-1, tlj-1)
        // are subtracted twice
        if (tli > 0 && tlj > 0)
            res = res + aux[tli-1][tlj-1];
     
        return res;
    }
     
    // Driver code
    public static void main (String[] args)
    {
        int mat[][] = {{1, 2, 3, 4, 6},
                       {5, 3, 8, 1, 2},
                       {4, 6, 7, 5, 5},
                       {2, 4, 8, 9, 4}};
                        
        int aux[][] = new int[M][N];
         
        preProcess(mat, aux);
         
        int tli = 2, tlj = 2, rbi = 3, rbj = 4;
        System.out.print("\nQuery1: "
            + sumQuery(aux, tli, tlj, rbi, rbj));
         
        tli = 0; tlj = 0; rbi = 1; rbj = 1;
        System.out.print("\nQuery2: "
            + sumQuery(aux, tli, tlj, rbi, rbj));
         
        tli = 1; tlj = 2; rbi = 3; rbj = 3;
        System.out.print("\nQuery3: "
            + sumQuery(aux, tli, tlj, rbi, rbj));
    }
}
 
// This code is contributed by Anant Agarwal.

Python3

# Python 3 program to compute submatrix
# query sum in O(1) time
 
M = 4
N = 5
 
# Function to preprocess input mat[M][N].
# This function mainly fills aux[M][N]
# such that aux[i][j] stores sum
# of elements from (0,0) to (i,j)
def preProcess(mat, aux):
     
    # Copy first row of mat[][] to aux[][]
    for i in range(0, N, 1):
        aux[0][i] = mat[0][i]
 
    # Do column wise sum
    for i in range(1, M, 1):
        for j in range(0, N, 1):
            aux[i][j] = mat[i][j] + aux[i - 1][j]
 
    # Do row wise sum
    for i in range(0, M, 1):
        for j in range(1, N, 1):
            aux[i][j] += aux[i][j - 1]
 
# A O(1) time function to compute sum of submatrix
# between (tli, tlj) and (rbi, rbj) using aux[][]
# which is built by the preprocess function
def sumQuery(aux, tli, tlj, rbi, rbj):
     
    # result is now sum of elements
    # between (0, 0) and (rbi, rbj)
    res = aux[rbi][rbj]
 
    # Remove elements between (0, 0)
    # and (tli-1, rbj)
    if (tli > 0):
        res = res - aux[tli - 1][rbj]
 
    # Remove elements between (0, 0)
    # and (rbi, tlj-1)
    if (tlj > 0):
        res = res - aux[rbi][tlj - 1]
 
    # Add aux[tli-1][tlj-1] as elements
    # between (0, 0) and (tli-1, tlj-1)
    # are subtracted twice
    if (tli > 0 and tlj > 0):
        res = res + aux[tli - 1][tlj - 1]
 
    return res
 
# Driver Code
if __name__ == '__main__':
    mat = [[1, 2, 3, 4, 6],
           [5, 3, 8, 1, 2],
           [4, 6, 7, 5, 5],
           [2, 4, 8, 9, 4]]
aux = [[0 for i in range(N)]
          for j in range(M)]
 
preProcess(mat, aux)
 
tli = 2
tlj = 2
rbi = 3
rbj = 4
print("Query1:", sumQuery(aux, tli, tlj, rbi, rbj))
 
tli = 0
tlj = 0
rbi = 1
rbj = 1
print("Query2:", sumQuery(aux, tli, tlj, rbi, rbj))
 
tli = 1
tlj = 2
rbi = 3
rbj = 3
print("Query3:", sumQuery(aux, tli, tlj, rbi, rbj))
 
# This code is contributed by
# Shashank_Sharma

C#

// C# program to compute submatrix
// query sum in O(1) time
using System;
 
class GFG
{
    static int M = 4;
    static int N = 5;
     
    // Function to preprocess input mat[M][N].
    // This function mainly fills aux[M][N]
    // such that aux[i][j] stores sum of
    // elements from (0,0) to (i,j)
    static int preProcess(int [,]mat, int [,]aux)
    {
        // Copy first row of mat[][] to aux[][]
        for (int i = 0; i < N; i++)
            aux[0,i] = mat[0,i];
         
        // Do column wise sum
        for (int i = 1; i < M; i++)
            for (int j = 0; j < N; j++)
                aux[i,j] = mat[i,j] + aux[i-1,j];
         
        // Do row wise sum
        for (int i = 0; i < M; i++)
            for (int j = 1; j < N; j++)
                aux[i,j] += aux[i,j-1];
                 
        return 0;
    }
     
    // A O(1) time function to compute sum
    // of submatrix between (tli, tlj) and
    // (rbi, rbj) using aux[][] which is
    // built by the preprocess function
    static int sumQuery(int [,]aux, int tli,
                        int tlj, int rbi, int rbj)
    {
        // result is now sum of elements
        // between (0, 0) and (rbi, rbj)
        int res = aux[rbi,rbj];
     
        // Remove elements between (0, 0)
        // and (tli-1, rbj)
        if (tli > 0)
            res = res - aux[tli-1,rbj];
     
        // Remove elements between (0, 0)
        // and (rbi, tlj-1)
        if (tlj > 0)
            res = res - aux[rbi,tlj-1];
     
        // Add aux[tli-1][tlj-1] as elements
        // between (0, 0) and (tli-1, tlj-1)
        // are subtracted twice
        if (tli > 0 && tlj > 0)
            res = res + aux[tli-1,tlj-1];
     
        return res;
    }
     
    // Driver code
    public static void Main ()
    {
        int [,]mat = {{1, 2, 3, 4, 6},
                      {5, 3, 8, 1, 2},
                      {4, 6, 7, 5, 5},
                      {2, 4, 8, 9, 4}};
                         
        int [,]aux = new int[M,N];
         
        preProcess(mat, aux);
         
        int tli = 2, tlj = 2, rbi = 3, rbj = 4;
         
        Console.Write("\nQuery1: " +
                      sumQuery(aux, tli, tlj, rbi, rbj));
         
        tli = 0; tlj = 0; rbi = 1; rbj = 1;
         
        Console.Write("\nQuery2: " +
                      sumQuery(aux, tli, tlj, rbi, rbj));
         
        tli = 1; tlj = 2; rbi = 3; rbj = 3;
         
        Console.Write("\nQuery3: " +
                      sumQuery(aux, tli, tlj, rbi, rbj));
    }
}
 
// This code is contributed by Sam007.

PHP

<?php
// PHP program to compute submatrix
// query sum in O(1) time
 
// Function to preprocess input mat[M][N].
// This function mainly fills aux[M][N]
// such that aux[i][j] stores sum
// of elements from (0,0) to (i,j)
function preProcess(&$mat, &$aux)
{
    $M = 4;
    $N = 5;
     
    // Copy first row of mat[][] to aux[][]
    for ($i = 0; $i < $N; $i++)
        $aux[0][$i] = $mat[0][$i];
     
    // Do column wise sum
    for ($i = 1; $i < $M; $i++)
        for ($j = 0; $j < $N; $j++)
            $aux[$i][$j] = $mat[$i][$j] +
                           $aux[$i - 1][$j];
     
    // Do row wise sum
    for ($i = 0; $i < $M; $i++)
        for ($j = 1; $j < $N; $j++)
            $aux[$i][$j] += $aux[$i][$j - 1];
}
 
// A O(1) time function to compute sum of
// submatrix between (tli, tlj) and
// (rbi, rbj) using aux[][] which is built
// by the preprocess function
function sumQuery(&$aux, $tli, $tlj, $rbi,$rbj)
{
    // result is now sum of elements
    // between (0, 0) and (rbi, rbj)
    $res = $aux[$rbi][$rbj];
 
    // Remove elements between (0, 0)
    // and (tli-1, rbj)
    if ($tli > 0)
    $res = $res - $aux[$tli - 1][$rbj];
 
    // Remove elements between (0, 0)
    // and (rbi, tlj-1)
    if ($tlj > 0)
    $res = $res - $aux[$rbi][$tlj - 1];
 
    // Add aux[tli-1][tlj-1] as elements between (0, 0)
    // and (tli-1, tlj-1) are subtracted twice
    if ($tli > 0 && $tlj > 0)
    $res = $res + $aux[$tli - 1][$tlj - 1];
 
    return $res;
}
 
// Driver Code
$mat = array(array(1, 2, 3, 4, 6),
             array(5, 3, 8, 1, 2),
             array(4, 6, 7, 5, 5),
             array(2, 4, 8, 9, 4));
 
preProcess($mat, $aux);
 
$tli = 2;
$tlj = 2;
$rbi = 3;
$rbj = 4;
echo ("Query1: ");
echo(sumQuery($aux, $tli, $tlj, $rbi, $rbj));
 
$tli = 0;
$tlj = 0;
$rbi = 1;
$rbj = 1;
echo ("\nQuery2: ");
echo(sumQuery($aux, $tli, $tlj, $rbi, $rbj));
 
 
$tli = 1;
$tlj = 2;
$rbi = 3;
$rbj = 3;
echo ("\nQuery3: ");
echo(sumQuery($aux, $tli, $tlj, $rbi, $rbj));
 
// This code is contributed by Shivi_Aggarwal
?>

Javascript

<script>
// Javascript program to compute submatrix query
// sum in O(1) time
 
     
    var M = 4;
    var N = 5;
     
    // Function to preprocess input mat[M][N].
    // This function mainly fills aux[M][N]
    // such that aux[i][j] stores sum of
    // elements from (0,0) to (i,j)
    function preProcess(mat, aux)
    {
         
        // Copy first row of mat[][] to aux[][]
        for (var i = 0; i < N; i++)
            aux[0,i] = mat[0,i];
         
        // Do column wise sum
        for (var i = 1; i < M; i++)
            for (var j = 0; j < N; j++)
                aux[i][j] = mat[i][j] +
                                aux[i-1][j];
         
        // Do row wise sum
        for (var i = 0; i < M; i++)
            for (var j = 1; j < N; j++)
                aux[i][j] += aux[i][j-1];
                 
        return 0;
    }
     
    // A O(1) time function to compute sum
    // of submatrix between (tli, tlj) and
    // (rbi, rbj) using aux[][] which is
    // built by the preprocess function
    function sumQuery( aux, tli, tlj, rbi, rbj)
    {
         
        // result is now sum of elements
        // between (0, 0) and (rbi, rbj)
        var res = aux[rbi][rbj];
     
        // Remove elements between (0, 0)
        // and (tli-1, rbj)
        if (tli > 0)
            res = res - aux[tli-1][rbj];
     
        // Remove elements between (0, 0)
        // and (rbi, tlj-1)
        if (tlj > 0)
            res = res - aux[rbi][tlj-1];
     
        // Add aux[tli-1][tlj-1] as elements
        // between (0, 0) and (tli-1, tlj-1)
        // are subtracted twice
        if (tli > 0 && tlj > 0)
            res = res + aux[tli-1][tlj-1];
     
        return res;
    }
     
    // Driver code
     
        var mat= [[1, 2, 3, 4, 6],
                       [5, 3, 8, 1, 2],
                       [4, 6, 7, 5, 5],
                       [2, 4, 8, 9, 4]];
                        
        var aux = new Array(M,N);
         
        preProcess(mat, aux);
         
        var tli = 2, tlj = 2, rbi = 3, rbj = 4;
        document.write("\nQuery1: "
            + sumQuery(aux, tli, tlj, rbi, rbj)+"<br>");
         
        tli = 0; tlj = 0; rbi = 1; rbj = 1;
        document.write("\nQuery2: "
            + sumQuery(aux, tli, tlj, rbi, rbj)+"<br>");
         
        tli = 1; tlj = 2; rbi = 3; rbj = 3;
        document.write("\nQuery3: "
            + sumQuery(aux, tli, tlj, rbi, rbj));
    }
}
 
// This code is contributed by shivanisinghss2110
</script>

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *