📜  子矩阵查询的XOR

📅  最后修改于: 2021-04-24 21:20:38             🧑  作者: 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


输出:
2
15