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: }
  • 相关阅读:
    开源项目
    [Accessibility] Missing contentDescription attribute on image [可取行]失踪contentDescription属性图像
    Android 布局 中实现适应屏幕大小及组件滚动
    EF 错误记录
    EasyUI 加载时需要显示和隐藏 panel(面板)内容破版问题
    IE 报表缩放后页面破版
    VS 2017 引入nuget 问题
    SSRS 报表显示页面 asp net session丢失或者找不到 asp net session has expired or could not be found()
    log4net 配置
    网站
  • 原文地址:https://www.cnblogs.com/allensun/p/1870107.html
Copyright © 2011-2022 走看看