您的位置:首页 > 其它

ACM: 树状数组 poj 2155  学习《浅…

2016-05-19 23:24 519 查看
Matrix
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

 

题意: 一个矩阵中状态只有0和1,两种操作:

                    
修改:
子矩阵:(x1,y1,x2,y2)每次改变一个子矩阵的状态(反转0->1,1->0);

                     查询: 每次查询具体某个(x,y) 

解题思路:

      1.
看了大牛的解题论文如梦初醒, 因为修改区间矩阵的状态, 可以用树状数组的特性修改,

        
如图:



         同过修改子矩阵的值,
由于判断0,1用奇偶判断即可, 每次修改都要有四个区域的修改.

        
这样保证只修改(x1,y1,x2,y2)子矩阵. (修改偶数次相当于不变, 负数不影响奇偶性);

      
2. 查询只要直接求子矩阵范围的奇偶性即可. (用笔在纸上画一画最清楚).

       3.
《浅谈信息学竞赛中的“0”和“1”》文章内有详细解释. 学习别人的好方法也是一种学习

          
方法. 集大家之所长.

 

代码:

#include
<cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 1005

int n, T;

int c[MAX][MAX];

int x1, y1, x2, y2;

int result;

char ch[2];

inline int lowbit(int x)

{

 return x & (-x);

}

void update(int x, int y, int val)

{

 int i, j;

 for(i = x; i <= n; i +=
lowbit(i))

 {

  for(j = y; j <=
n; j += lowbit(j))

   c[i][j] +=
val;

 }

}

int getSum(int x, int y)

{

 int sum = 0;

 int i, j;

 for(i = x; i > 0; i -=
lowbit(i))

 {

  for(j = y; j >
0; j -= lowbit(j))

   sum +=
c[i][j];

 }

 return sum;

}

int main()

{

// freopen("input.txt", "r", stdin);

 int caseNum, i;

 scanf("%d",&caseNum);

 while(caseNum--)

 {

  memset(c, 0, sizeof(c));

  scanf("%d
%d",&n, &T);

  for(i = 0; i <
T; ++i)

  {

   scanf("%s",ch);

   if(ch[0] ==
'C')

   {

    scanf("%d
%d %d %d",&x1, &y1,
&x2, &y2);

    update(x1,
y1, 1);

    update(x2+1,
y1, -1);

    update(x1,
y2+1, -1);

    update(x2+1,
y2+1, -1);

   }

   else if(ch[0]
== 'Q')

   {

    scanf("%d
%d",&x1, &y1);

    result
= getSum(x1, y1);

    printf("%d\n",1&result);

   }

  }

  if(caseNum != 0)

   printf("\n");

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: