鏈接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 }