📜  子矩阵查询的XOR

📅  最后修改于: 2021-05-25 08:18:18             🧑  作者: Mango

给定一个N * N矩阵和q个查询,每个查询包含一个矩形子矩阵的左上角和右下角的位置,任务是从该子矩阵中查找所有元素的异或。
例子:

一个简单的解决方案是为每个查询找到整个子矩阵的XOR。因此,每个查询的最坏情况时间复杂度将为O(n 2 )。
高效的方法:我们都熟悉线性数组上的前缀XOR的想法,即

我们将尝试将其扩展到二维矩阵。我们将计算一个前缀XOR矩阵,这将有助于我们解决O(1)中的每个查询。
在这种情况下,我们在(R,C)位置的前缀XOR矩阵将存储矩形子矩阵的XOR,其左上角位于(0,0),右下角位于(R,C)。
我们分两步计算前缀XOR。

  1. 从左到右为原始矩阵的每一行计算prefix-XOR。
  2. 在上面的矩阵上,从上到下为每列计算前缀XOR。

一旦有了所需的前缀XOR-matrix,我们就可以简单地回答查询。从(R1,C1)到(R2,C2)的子矩阵的XOR可以计算为prefix_xor [R2] [C2] ^ prefix_xor [R1-1 –] [C2] ^ prefix_xor [R2] [C1-1] ^ prefix_xor [R1 – 1] [C1 – 1]
注意:如果R1或C1等于0,则R1 – 1或C1 – 1也应为0。
下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
#define n 3
using namespace std;
 
// Function to pre-compute the xor
void preComputeXor(int arr[][n], int prefix_xor[][n])
{
    // Left to right prefix xor
    // for each row
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            if (j == 0)
                prefix_xor[i][j] = arr[i][j];
            else
                prefix_xor[i][j]
                    = (prefix_xor[i][j - 1] ^ arr[i][j]);
        }
 
    // Top to bottom prefix xor
    // for each column
    for (int i = 0; i < n; i++)
        for (int j = 1; j < n; j++)
            prefix_xor[j][i]
                = (prefix_xor[j - 1][i] ^ prefix_xor[j][i]);
}
 
// Function to process the queries
// x1, x2, y1, y2 represent the
// positions of the top-left
// and bottom right corners
int ansQuerie(int prefix_xor[][n], int x1, int y1, int x2, int y2)
{
 
    // To store the xor values
    int xor_1 = 0, xor_2 = 0, xor_3 = 0;
 
    // Finding the values we need to xor
    // with value at (x2, y2) in prefix-xor
    // matrix
    if (x1 != 0)
        xor_1 = prefix_xor[x1 - 1][y2];
    if (y1 != 0)
        xor_2 = prefix_xor[x2][y1 - 1];
    if (x1 != 0 and y1 != 0)
        xor_3 = prefix_xor[x1 - 1][y1 - 1];
 
    // Return the required prefix xor
    return ((prefix_xor[x2][y2] ^ xor_1) ^ (xor_2 ^ xor_3));
}
 
// Driver code
int main()
{
    int arr[][n] = { { 1, 2, 3 },
                     { 4, 5, 6 },
                     { 7, 8, 9 } };
 
    // To store pre-computed xor
    int prefix_xor[n][n];
 
    // Pre-computing xor
    preComputeXor(arr, prefix_xor);
 
    // Queries
    cout << ansQuerie(prefix_xor, 1, 1, 2, 2) << endl;
    cout << ansQuerie(prefix_xor, 1, 2, 2, 2) << endl;
    return 0;
}


Java
// Java implementation of the approach
class GfG
{
     
static int n = 3;
 
// Function to pre-compute the xor
static void preComputeXor(int arr[][],
                            int prefix_xor[][])
{
    // Left to right prefix xor
    // for each row
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            if (j == 0)
                prefix_xor[i][j] = arr[i][j];
            else
                prefix_xor[i][j] =
                    (prefix_xor[i][j - 1] ^ arr[i][j]);
        }
 
    // Top to bottom prefix xor
    // for each column
    for (int i = 0; i < n; i++)
        for (int j = 1; j < n; j++)
            prefix_xor[j][i] =
                (prefix_xor[j - 1][i] ^ prefix_xor[j][i]);
}
 
// Function to process the queries
// x1, x2, y1, y2 represent the
// positions of the top-left
// and bottom right corners
static int ansQuerie(int prefix_xor[][], int x1,
                    int y1, int x2, int y2)
{
 
    // To store the xor values
    int xor_1 = 0, xor_2 = 0, xor_3 = 0;
 
    // Finding the values we need to xor
    // with value at (x2, y2) in prefix-xor
    // matrix
    if (x1 != 0)
        xor_1 = prefix_xor[x1 - 1][y2];
    if (y1 != 0)
        xor_2 = prefix_xor[x2][y1 - 1];
    if (x1 != 0 && y1 != 0)
        xor_3 = prefix_xor[x1 - 1][y1 - 1];
 
    // Return the required prefix xor
    return ((prefix_xor[x2][y2] ^ xor_1) ^ (xor_2 ^ xor_3));
}
 
// Driver code
public static void main(String[] args)
{
    int arr[][] = new int[][]{{ 1, 2, 3 },
                            { 4, 5, 6 },
                            { 7, 8, 9 }};
 
    // To store pre-computed xor
    int prefix_xor[][] = new int[n][n];
 
    // Pre-computing xor
    preComputeXor(arr, prefix_xor);
 
    // Queries
    System.out.println(ansQuerie(prefix_xor, 1, 1, 2, 2));
    System.out.println(ansQuerie(prefix_xor, 1, 2, 2, 2));
}
}
 
// This code is contributed by
// Prerna Saini.


Python3
n = 3
 
# Function to pre-compute the xor
def preComputeXor(arr, prefix_xor):
     
    # Left to right prefix xor
    # for each row
    for i in range(n):
        for j in range(n):
            if (j == 0):
                prefix_xor[i][j] = arr[i][j]
            else:
                prefix_xor[i][j] = (prefix_xor[i][j - 1] ^
                                               arr[i][j])
 
    # Top to bottom prefix xor
    # for each column
    for i in range(n):
        for j in range(1, n):
            prefix_xor[j][i] = (prefix_xor[j - 1][i] ^
                                    prefix_xor[j][i])
 
# Function to process the queries
# x1, x2, y1, y2 represent the
# positions of the top-left
# and bottom right corners
def ansQuerie(prefix_xor, x1, y1, x2, y2):
 
    # To store the xor values
    xor_1, xor_2, xor_3 = 0, 0, 0
 
    # Finding the values we need to xor
    # with value at (x2, y2) in prefix-xor
    # matrix
    if (x1 != 0):
        xor_1 = prefix_xor[x1 - 1][y2]
    if (y1 != 0):
        xor_2 = prefix_xor[x2][y1 - 1]
    if (x1 != 0 and y1 != 0):
        xor_3 = prefix_xor[x1 - 1][y1 - 1]
 
    # Return the required prefix xor
    return ((prefix_xor[x2][y2] ^ xor_1) ^
                         (xor_2 ^ xor_3))
 
 
# Driver code
arr = [[ 1, 2, 3 ],
       [ 4, 5, 6 ],
       [ 7, 8, 9 ]]
 
# To store pre-computed xor
prefix_xor = [[0 for i in range(n)]
                 for i in range(n)]
 
# Pre-computing xor
preComputeXor(arr, prefix_xor)
 
# Queries
print(ansQuerie(prefix_xor, 1, 1, 2, 2))
print(ansQuerie(prefix_xor, 1, 2, 2, 2))
 
# This code is contributed by Mohit Kumar


C#
// C# implementation of the approach
using System;
 
class GfG
{
    static int n = 3;
     
    // Function to pre-compute the xor
    static void preComputeXor(int [,]arr,
                                int [,]prefix_xor)
    {
        // Left to right prefix xor
        // for each row
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
            {
                if (j == 0)
                    prefix_xor[i, j] = arr[i, j];
                else
                    prefix_xor[i, j] =
                   (prefix_xor[i, j - 1] ^ arr[i, j]);
            }
     
        // Top to bottom prefix xor
        // for each column
        for (int i = 0; i < n; i++)
            for (int j = 1; j < n; j++)
                prefix_xor[j, i] =
                    (prefix_xor[j - 1, i] ^
                     prefix_xor[j, i]);
    }
     
    // Function to process the queries
    // x1, x2, y1, y2 represent the
    // positions of the top-left
    // and bottom right corners
    static int ansQuerie(int [,]prefix_xor, int x1,
                         int y1, int x2, int y2)
    {
     
        // To store the xor values
        int xor_1 = 0, xor_2 = 0, xor_3 = 0;
     
        // Finding the values we need to xor
        // with value at (x2, y2) in prefix-xor
        // matrix
        if (x1 != 0)
            xor_1 = prefix_xor[x1 - 1, y2];
        if (y1 != 0)
            xor_2 = prefix_xor[x2, y1 - 1];
        if (x1 != 0 && y1 != 0)
            xor_3 = prefix_xor[x1 - 1, y1 - 1];
     
        // Return the required prefix xor
        return ((prefix_xor[x2,y2] ^ xor_1) ^
                            (xor_2 ^ xor_3));
    }
     
    // Driver code
    public static void Main()
    {
        int [,]arr = {{ 1, 2, 3 },
                      { 4, 5, 6 },
                      { 7, 8, 9 }};
     
        // To store pre-computed xor
        int [,]prefix_xor = new int[n, n];
     
        // Pre-computing xor
        preComputeXor(arr, prefix_xor);
     
        // Queries
        Console.WriteLine(ansQuerie(prefix_xor, 1, 1, 2, 2));
        Console.WriteLine(ansQuerie(prefix_xor, 1, 2, 2, 2));
    }
}
 
// This code is contributed by Ryuga


PHP


Javascript


输出:
2
15

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。