二维树状数组
Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N).
We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.
1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].
Input
We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.
1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].
The first line of the input is an integer X (X <= 10)
representing the number of test cases. The following X blocks each
represents a test case.
The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.
Output
The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.
For each querying output one line, which has an integer representing A[x, y].
There is a blank line between every two continuous test cases.
Sample Input
There is a blank line between every two continuous test cases.
1 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 1Sample Output
1 0 0 1
题意 : 给你一个矩阵,每次可以修改一个子矩阵,将 0 变成 1, 将 1 变成 0, 然后再给你一些询问,询问具体的某个位置的值是 0 还是 1
思路分析 : 首先某个位置的值只要看其修改的次数就可以,修改奇数次为 1, 偶数次 为 0
我们都知道,树状数组向上更新可以实现单点更新,向下可以实现区间查询,在这里,我们通过一个转换,就可以实现区间更新,单点查询了。
在一维的情况下,我们如果想要将区间 [a, b] 的值都加上 val , 那么就可以让区间 [1, b] 的值都加上 val , 再让 [1, a-1] 的值都减去 val 即可,最后查询某个点的值就只需要
向上统计它全部的父节点的就可以了。
代码示例 :
#define ll long long const int maxn = 1e6+5; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; int n, m; int c[1005][1005]; int a1, b1, a2, b2; int lowbit(int x){return x&(-x);} void update(int x, int y, int val){ for(int i = x; i > 0; i -= lowbit(i)){ for(int j = y; j > 0; j -= lowbit(j)){ c[i][j] += val; } } } int sum(int x, int y){ int ret = 0; for(int i = x; i <= n; i += lowbit(i)){ for(int j = y; j <= n; j += lowbit(j)){ ret += c[i][j]; } } return ret; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int t; char s[5]; cin >> t; while(t--){ cin >> n >> m; memset(c, 0, sizeof(c)); for(int i = 1; i <= m; i++){ scanf("%s", s); if (s[0] == 'C'){ scanf("%d%d%d%d", &a1, &b1, &a2, &b2); update(a2, b2, 1); update(a1-1, b1-1, 1); update(a1-1, b2, -1); update(a2, b1-1, -1); } else { scanf("%d%d", &a1, &b1); int f = sum(a1, b1); if (f&1) printf("1\n"); else printf("0\n"); } } printf("\n"); } return 0; }
东北日出西边雨 道是无情却有情