POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)
Posted ljbguanli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)相关的知识,希望对你有一定的参考价值。
POJ - 2155
Description
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
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
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 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 1 Sample Output 1 0 0 1 题目意思是给你一个矩阵,最開始都是为0,然后给你一个左上角的坐标,右下角的坐标,将这个区域的0 -> 1,1 -> 0,然后给你一个点让你求出他此时的结果是1还是0. 这里能够用树状数组的区间改动以及单点求值。仅仅是这里是二维的树状数组,原理是一样的。 将其改变的话,能够如此,如果最開始[1....x2][1....y2]为偶数的话(这里就是看成是前辍和) 先将[1....x2][1....y2]添加1,变为奇数,然后将[1...x1 - 1][y2]添加1变为偶数,将[1....x2][y1]添加1变为偶数,而他们中间重叠的[1....x1 - 1][1....x2 - 1]部分则是被改变了三次。还是奇数,所以还有加1。将他变为偶数,如此除了[x1....x2][y1....y2]变了外。其它的地方依然没有改变。 /* Author: 2486 Memory: 4304 KB Time: 547 MS Language: G++ Result: Accepted */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1000 + 5; int C[MAXN][MAXN]; int N, X, M, x, y, x1, x2, y1, y2; char op[10]; int lowbits(int x){ return x & (-x); } void add(int x,int y){ for(int i = x; i <= N;i += lowbits(i)){ for(int j = y;j <= N;j += lowbits(j)){ C[i][j] ++; } } } int query(int x,int y){ int ret = 0; for(int i = x;i > 0;i -= lowbits(i)){ for(int j = y;j > 0;j -= lowbits(j)){ ret += C[i][j]; } } return ret; } int main(){ //freopen("D://imput.txt","r",stdin); scanf("%d", &X); while(X --){ memset(C, 0, sizeof(C)); scanf("%d%d", &N, &M); while(M --){ scanf("%s", op); if(op[0] == ‘C‘){ scanf("%d%d%d%d", &x1, &y1, &x2, &y2); x2 ++; y2 ++; add(x1, y1); add(x1, y2); add(x2, y1); add(x2, y2); } else{ scanf("%d%d", &x, &y); printf("%d\n", query(x,y) & 1);//求和即代表求点 } } if(X)printf("\n"); } return 0; } 线段树代码: /* Author: 2486 Memory: 63688 KB Time: 1579 MS Language: G++ Result: Accepted */ #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r #define root 1, 1, N const int MAXN = 1000 + 5; int N, T, CASE, x1, y1, x2, y2, ret, x, y; char op[5]; int sum[MAXN << 2][MAXN << 2]; void update_r(int cr, int y1, int y2, int rt, int l, int r) { if(y1 <= l && r <= y2) { sum[cr][rt] = !sum[cr][rt]; return ; } int mid = (l + r) >> 1; if(y1 <= mid) update_r(cr, y1, y2, lson); if(y2 > mid) update_r(cr, y1, y2, rson); } void update_c(int x1, int y1, int x2, int y2, int rt, int l, int r) { if(x1 <= l && r <= x2) { update_r(rt, y1, y2, root); return; } int mid = (l + r) >> 1; if(x1 <= mid) update_c(x1, y1, x2, y2, lson); if(x2 > mid) update_c(x1, y1, x2, y2, rson); } void query_r(int cr, int y1, int y2, int rt, int l, int r) { if(sum[cr][rt]) ret ++; if(y1 <= l && r <= y2) { return ; } int mid = (l + r) >> 1; if(y1 <= mid) query_r(cr, y1, y2, lson); if(y2 > mid) query_r(cr, y1, y2, rson); } void query_c(int x1, int y1, int x2, int y2, int rt, int l, int r) { query_r(rt, y1, y2, root);//选择覆盖了子树的个数 if(x1 <= l && r <= x2) { return; } int mid = (l + r) >> 1; if(x1 <= mid) query_c(x1, y1, x2, y2, lson); if(x2 > mid) query_c(x1, y1, x2, y2, rson); } int main() { //freopen("D://imput.txt","r",stdin); scanf("%d", &CASE); while(CASE --) { memset(sum, 0, sizeof(sum)); scanf("%d%d", &N, &T); while(T --) { scanf("%s", op); if(op[0] == ‘C‘) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); update_c(x1, y1, x2, y2, root); } else { scanf("%d%d", &x, &y); ret = 0; query_c(x, y, x, y, root); printf("%d\n", ret & 1); } } if(CASE)printf("\n"); } return 0; } |
以上是关于POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2155 Matrix二维树状数组+YY(区间更新,单点查询)
POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)