计蒜客 矩阵操作
题目描述
给出 $N \times N$ 的矩阵 $A$,其中的元素是 $0$ 或 $1$。初始时均为 $0$。
我们可以修改矩阵,给定左上角 $(x_1, y_1)$,和右下角 $(x_2,y_2)$,对这个矩阵的所有元素执行取反操作,即 $0$ 变成 $1$,$1$ 变成 $0$。
现在我们一共有两种操作:
- $C \ x_1 \ y_1 \ x_2 \ y_2 (1\leq x1\leq x2\leq n, 1\leq y1\leq y2\leq)$:修改矩形
- $Q \ x \ y (1\leq x, y\leq)$:查询 $A_{x,y}$ 的值
样例
输入格式
第一行两个整数 $N,T(2\leq N\leq 1000, 1\leq T\leq 50000)$。
接下来 $T$ 行,每行一个操作。
2 10 C 2 1 2 2 Q 2 2 C 2 1 2 1 Q 1 1 C 1 1 2 1 C 1 2 1 2 C 1 1 2 2 Q 1 1 C 1 1 2 1 Q 2 1
输出格式
对于每个查询操作,一行一个整数表示 $A_{x,y}$。
1 0 0 1
算法与数据结构
树状数组
题解
二维树状数组
完整代码
#include <bits/stdc++.h> using namespace std; int n = 0; const int MAX_N = 1007; int C[MAX_N][MAX_N] = {{0}}; // 树状数组 C int lowBit(int x) { return x & -x; // return x & (x ^ (x - 1)) } // 查询 int sum(int i, int j){ int res = 0; for(int x = i; x; x -= lowBit(x)) for(int y = j; y; y -= lowBit(y)) res += C[x][y]; return res; } // 修改 void change(int i, int j, int delta){ for(int x = i; x < MAX_N; x += lowBit(x)) { for (int y = j; y < MAX_N; y += lowBit(y)) { C[x][y] += delta; } } } // 子矩阵的操作只需要使用 4 个树状数组矩阵的容斥就可以解决 // 子矩阵修改 void subChange(int x1, int y1, int x2, int y2) { int delta = 1; // 本题记录操作次数,因此 delta 为 1 change(x1, y1, delta); change(x1, y2 + 1, delta); change(x2 + 1, y1, delta); change(x2 + 1, y2 + 1, delta); } int main() { int t; scanf("%d%d", &n, &t); for (int i = 0; i < t; i++) { char op; scanf("\n%c", &op); if (op == 'C') { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); subChange(x1, y1, x2, y2); } else { int x, y; scanf("%d%d", &x, &y); printf("%d\n", sum(x, y) % 2); } } return 0; }