POJ 2155 Matrix【二维树状数组+YY(区间计数)】

题目链接:http://poj.org/problem?id=2155

Matrix

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 32950   Accepted: 11943

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

Source

POJ Monthly,Lou Tiancheng

题意概括:

有一个初始值为0的N*N的二维矩阵,有T次操作,每次操作有两种选择:

C : 修改以(x1, y1)为左上角(x2, y2)为右下角的矩阵的值(0和1互换)

Q:查询(x, y)的值为 0 或者 为 1;

解题思路:

涉及到多次区间修改和区间查询的优先考虑线段树和树状数组,这道题巧妙之处在于灵活运用树状数组的前缀和,把区间修改转换单点修改,一维需要标记两个点而二维需要标记四个点,一个点用于发挥效果,另外三个点用于消除效果,因为树状数组维护的是前缀和,而对于二维树状数组,查询的则是以(1,1)为左上角,(x,y)为右下角的矩阵的和。

第二就是我们可以借助修改次数的奇偶性来判断该点的值为 0 / 1;

例如:N = 3;C:x1 = 1, y1 = 1, x2 = 2, y2 = 2;

1   1
  (x,y)  
1   1

(因为我们只需要知道奇偶性,所以矩阵外的点加1即可消除效果)

AC code:

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long int;
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 1e3+; int mmp[MAXN][MAXN];
int N, T; int lowbit(int x)
{
return x&(-x);
} void add(int x, int y, int value)
{
for(int i = x; i <= N; i += lowbit(i))
for(int j = y; j <= N; j += lowbit(j))
mmp[i][j]+=value;
} int sum(int x, int y)
{
int res = ;
for(int i = x; i > ; i -= lowbit(i))
for(int j = y; j > ; j -= lowbit(j))
res+=mmp[i][j];
return res;
} void init()
{
for(int i = ; i <= N; i++)
for(int j = ; j <= N; j++)
mmp[i][j] = ;
} int main()
{
int T_case;
char com[];
int x, y, x1, x2, y1, y2;
scanf("%d", &T_case);
while(T_case--)
{
scanf("%d%d", &N, &T);
init();
while(T--)
{
scanf("%s", &com);
if(com[] == 'C')
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
add(x1, y1, );
add(x2+, y1, );
add(x1, y2+, );
add(x2+, y2+, );
}
else if(com[] == 'Q')
{
scanf("%d%d", &x, &y);
int res = ;
res = sum(x, y);
// printf("res: %d\n", res);
if(res%) printf("1\n");
else printf("0\n");
}
}
puts("");
}
return ;
}
上一篇:android之滑屏的实现


下一篇:Redis面试题记录--缓存双写情况下导致数据不一致问题