📜  子矩阵查询的XOR(1)

📅  最后修改于: 2023-12-03 14:53:24.866000             🧑  作者: Mango

子矩阵查询的XOR

简介

子矩阵查询的XOR是指给定一个矩阵,并对其进行若干次查询。每次查询要求计算矩阵中某个子矩阵内的所有元素的异或和。

算法介绍

对于这个问题,我们可以使用前缀异或和的方法来解决。具体地,我们可以用一个二维数组a来存储矩阵中每一个元素的值。然后,我们可以预处理出一个二维前缀异或和数组p,其中p[i][j]表示原矩阵中(1,1)(i,j)这个子矩阵内所有元素的异或和。

int a[N][N], p[N][N];
// 初始化a数组和p数组
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
        cin >> a[i][j];
        p[i][j] = p[i - 1][j] ^ p[i][j - 1] ^ p[i - 1][j - 1] ^ a[i][j];
    }
}

接下来,对于每次查询,我们只需要根据预处理出的前缀异或和数组,计算子矩阵的异或和即可。具体地,对于一个查询(x1,y1)(x2,y2)这个子矩阵的异或和,我们可以用下面这个式子来计算:

int ans = p[x2][y2] ^ p[x2][y1 - 1] ^ p[x1 - 1][y2] ^ p[x1 - 1][y1 - 1];

这个式子的含义是,先计算以(1,1)为左上角,以(x2,y2)为右下角的矩形内所有元素的异或和,再减去以(1,1)为左上角,以(x2,y1-1)为右下角的矩形内所有元素的异或和,以及以(1,1)为左上角,以(x1-1,y2)为右下角的矩形内所有元素的异或和,最后再加上以(1,1)为左上角,以(x1-1,y1-1)为右下角的矩形内所有元素的异或和,即可得到该子矩阵的异或和。

时间复杂度

预处理出前缀异或和数组的时间复杂度为$O(nm)$,每次查询的时间复杂度为$O(1)$。因此,总时间复杂度为$O(nm+q)$,其中$q$为查询次数。

参考代码
const int N = 1005;

int a[N][N], p[N][N];

int main() {
    int n, m;
    cin >> n >> m;
    // 初始化a数组和p数组
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
            p[i][j] = p[i - 1][j] ^ p[i][j - 1] ^ p[i - 1][j - 1] ^ a[i][j];
        }
    }
    int q;
    cin >> q;
    while (q--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        // 计算子矩阵的异或和
        int ans = p[x2][y2] ^ p[x2][y1 - 1] ^ p[x1 - 1][y2] ^ p[x1 - 1][y1 - 1];
        cout << ans << endl;
    }
    return 0;
}