zoukankan      html  css  js  c++  java
  • 【原】 POJ 2155 Matrix 2D树状数组 解题报告

    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

       1: const int N = 1001 ;
       2:  
       3: int tree[N][N] = {0} ;
       4:  
       5: //此过程是向上求的,不同于标准向下求
       6: int GetSum( int n, int x, int y )
       7: {
       8:     int y1 ;
       9:     int sum = 0 ;
      10:     while( x<=n ) //***
      11:     {
      12:         y1 = y ;
      13:         while( y1<=n )
      14:         {
      15:             sum += tree[x][y1] ;
      16:             y1 += ( y1 & -y1 ) ;  //***
      17:         }
      18:         x += ( x & -x ) ;
      19:     }
      20:     return sum ;
      21: }
      22:  
      23: //此过程是向下求的,不同于标准向上求
      24: void AddVal( int x, int y, int val )
      25: {
      26:     int y1 ;
      27:     while( x>0 )  //***
      28:     {
      29:         y1 = y ;
      30:         while( y1>0 )
      31:         {
      32:             tree[x][y1] += val ;
      33:             y1 -= ( y1 & -y1 ) ;  //***
      34:         }
      35:         x -= ( x & -x ) ;
      36:     }
      37: }
      38:  
      39: void run2155()
      40: {
      41:     int caseNum,n,t ;
      42:     char c ;
      43:     int x1,y1,x2,y2 ;
      44:     int i ;
      45:  
      46:     scanf( "%d" , &caseNum ) ;
      47:     while( caseNum-- )
      48:     {
      49:         scanf( "%d%d", &n,&t ) ;
      50:  
      51:         memset(tree,0,sizeof(tree)) ; //对数组赋值
      52:  
      53:         while( t-- )
      54:         {
      55:             scanf( "\n%c", &c ) ;
      56:             if( c=='C' )
      57:             {
      58:                 scanf( "%d%d%d%d", &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:             }
      64:             else
      65:             {
      66:                 scanf( "%d%d", &x1,&y1 ) ;
      67:                 printf( "%d\n", GetSum(n,x1,y1)%2 ) ;
      68:             }
      69:         }
      70:         printf("\n") ;
      71:     }
      72: }
  • 相关阅读:
    函数重载和函数指针在一起
    Uva
    Uva
    Uva
    Uva
    Uva
    CCPC-Wannafly-day5
    CCPC-Wannafly-day3
    CCPC-Wannafly-day2
    CCPC-Wannafly-Winter 2020.01.12总结
  • 原文地址:https://www.cnblogs.com/allensun/p/1870107.html
Copyright © 2011-2022 走看看