📅  最后修改于: 2023-12-03 14:53:24.866000             🧑  作者: Mango
子矩阵查询的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;
}