http://poj.org/problem?id=2155

 

题目要求修改一个区域,然后求一个元素的值。貌似和树状数组的功能完全相反。但这题,应该
说这个思路的精妙之处就体现在这里。我认为关键是要理解“树状”的概念。画一个一维的树状数
组图形,就会发现所有的元素都会链接到2,4,8,16,32……这条“主干”上来。那么,修改了“主干”,
其实就相当于修改了整个“树”。

对于每个元素a,“主干”可以分为两个部分,
Up(a) = { a1 = a, a2 = a1+ lowbit(a1), a3 = a2 + lowbit(a2), ... }
Down(a) = { a1 =a, a2 = a1 -lowbit(a1), a3 = a2 - lowbit(a2), ... }。
当然这里不是完全的对应主干上的每个元素。对于任意a<b,up(a)与down(b)的交集都只有一个元素。
若要对[a,b]内的元素进行+n操作,只要down(a-1)的元素-n, down(b)的元素+n就好了。

设a<=c<=b,查询c时则对up(c)进行求和。因为up(c)与down(b)只有一个共同元素,所以可以完整的
体现修改。以上是一维的情况。可以非常直接的推论到二维。只要对x, y坐标同时up或down。理解了
上面的思路,这题就迎刃而解了。

 

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

 

int N = 1001 ;
   2:  
int tree[N][N] = {0} ;
   4:  
//此过程是向上求的,不同于标准向下求
int y )
   7: {
int y1 ;
int sum = 0 ;
//***
  11:     {
  12:         y1 = y ;
while( y1<=n )
  14:         {
  15:             sum += tree[x][y1] ;
//***
  17:         }
  18:         x += ( x & -x ) ;
  19:     }
return sum ;
  21: }
  22:  
//此过程是向下求的,不同于标准向上求
int val )
  25: {
int y1 ;
//***
  28:     {
  29:         y1 = y ;
while( y1>0 )
  31:         {
  32:             tree[x][y1] += val ;
//***
  34:         }
  35:         x -= ( x & -x ) ;
  36:     }
  37: }
  38:  
void run2155()
  40: {
int caseNum,n,t ;
char c ;
int x1,y1,x2,y2 ;
int i ;
  45:  
 , &caseNum ) ;
while( caseNum-- )
  48:     {
, &n,&t ) ;
  50:  
//对数组赋值
  52:  
while( t-- )
  54:         {
, &c ) ;
'C' )
  57:             {
, &x1,&y1,&x2,&y2 ) ;
  59:                 AddVal( x2, y2, 1 ) ;
  60:                 AddVal( x1-1, y2, -1 ) ;
  61:                 AddVal( x2, y1-1, -1 ) ;
  62:                 AddVal( x1-1, y1-1, 1 ) ;
  63:             }
else
  65:             {
, &x1,&y1 ) ;
, GetSum(n,x1,y1)%2 ) ;
  68:             }
  69:         }
) ;
  71:     }
  72: }

相关文章: