POJ2155Matrix(二维线段树)
链接http://poj.org/problem?id=2155
题目操作就是说,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1.
方法:二维线段树,这个东东我纠结了好久才慢慢弄好。二维线段树其实就就是在第一位区间的每个节点下再建一颗线段树,表示第二维的区间。
在修改的时候只需要先找到第一维的对应区间,在在这个区间的弟二维中查找对应区间,再做修改即可。而查找的时候,由于不同的第一维区间可能会有包含关系,所以需要对每个目标所在第一维区间查找第二维区间。
比如线段树的区间大小是3×3,那么在查找第一维区间是[1,2],第二维区间是[1,2]时,就需要在线段树第一维的[1,3]和[1,2]两个区间对第二维进行查找,因为修改操作的时候可能修改了第一维的[1,3]区间,同时也修改了[1,2]区间,这样的话就不能仅仅只查找某一个第一维的区间。
至于本题的解法,我们可以在修改时标记某一个节点,那么这个节点以下的区间就都是要修改的,当我们在查找的时候,只需要统计查找到这个点时,一路上有多少个被修改的区间,是偶数说明呗修改回来了,是奇数那就是被修改了。
1 #include <stdio.h> 2 #include <string.h> 3 #define xlson kx<<1, xl, mid 4 #define xrson kx<<1|1, mid+1, xr 5 #define ylson ky<<1, yl, mid 6 #define yrson ky<<1|1, mid+1, yr 7 #define MAXN 1005 8 #define mem(a) memset(a, 0, sizeof(a)) 9 10 bool tree[MAXN<<2][MAXN<<2]; 11 int X, N, T; 12 int num, X1, X2, Y1, Y2; 13 char ch; 14 15 void editY(int kx,int ky,int yl,int yr) 16 { 17 if(Y1<=yl && yr<=Y2) 18 { 19 tree[kx][ky] = !tree[kx][ky]; 20 return ; 21 } 22 int mid = (yl+yr)>>1; 23 if(Y1 <= mid) editY(kx,ylson); 24 if(Y2 > mid) editY(kx,yrson); 25 } 26 27 void editX(int kx,int xl,int xr) 28 { 29 if(X1<=xl && xr<=X2) 30 { 31 editY(kx,1,1,N); 32 return ; 33 } 34 int mid = (xl+xr)>>1; 35 if(X1 <= mid) editX(xlson); 36 if(X2 > mid) editX(xrson); 37 } 38 39 void queryY(int kx,int ky,int yl,int yr) 40 { 41 if(tree[kx][ky]) num ++; 42 if(yl==yr) return ; 43 int mid = (yl+yr)>>1; 44 if(Y1 <= mid) queryY(kx,ylson); 45 else queryY(kx,yrson); 46 } 47 48 void queryX(int kx,int xl,int xr) 49 { 50 queryY(kx,1,1,N); 51 if(xl==xr) return ; 52 int mid = (xl+xr)>>1; 53 if(X1 <= mid)queryX(xlson); 54 else queryX(xrson); 55 } 56 57 58 int main() 59 { 60 while(~scanf("%d", &X))while(X--) 61 { 62 mem(tree); 63 scanf("%d %d%*c", &N,&T); 64 for(int i=0;i<T;i++) 65 { 66 scanf("%c %d %d%*c",&ch,&X1,&Y1); 67 if(ch == 'C') 68 { 69 scanf("%d %d%*c", &X2, &Y2); 70 editX(1,1,N); 71 } 72 else 73 { 74 num = 0; 75 queryX(1,1,N); 76 if(num & 1)printf("1\n"); 77 else printf("0\n"); 78 } 79 } 80 if(X) printf("\n"); 81 } 82 return 0; 83 }