题解【POJ2155】Matrix

Description

Given an \(N \times 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 \leq i, j \leq 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 \leq x1 \leq x2 \leq n, 1 \leq y1 \leq y2 \leq 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 \leq x, y \leq n)\) querys \(A[x, y]\).

Input

The first line of the input is an integer \(X (X \leq 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 \leq N \leq 1000, 1 \leq T \leq 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

Solution

题意简述:一个\(N \times N\)\(01\)矩阵,和几种动态操作,包括对子矩阵\((x,y,xx,yy)\)的所有元素异或,查询某一点\((x,y)\)的元素值。

二维树状数组裸题。

异或的操作不难修改。

二维树状数组与一维树状数组不同的是:

  • 一维树状数组维护的是一条链,而二维树状数组维护的却是一片区域。
  • 一维树状数组更新和查找只有一重循环,而二维树状数组需要两重循环。
  • 二维树状数组比一维树状数组多一维度。

经过以上分析,\(AC\)代码就不难得出了。

Code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>

using namespace std;

inline int gi()
{
    int f = 1, x = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
    return f * x;
}

int n, m, c[1003][1003], t;
bool fl = false;

inline void add(int x, int y)//二维树状数组的修改操作
{
    for (int i = x; i <= n; i = i + (i & (-i)))
    {
        for (int j = y; j <= n; j = j + (j & (-j)))//注意两重循环
        {
            ++c[i][j];
        }
    }
}

inline int getans(int x, int y)//二维树状数组的查询操作
{
    int ans = 0;
    for (int i = x; i; i = i - (i & (-i)))
    {
        for (int j = y; j; j = j - (j & (-j)))
        {
            ans = ans + c[i][j];//加上答案
        }
    }
    return ans;
}

int main()
{
    int t = gi();
    while (t--)
    {
        if (!fl) fl = true;
        else puts("");
        n = gi(), m = gi();
        memset(c, 0, sizeof(c));
        while (m--)
        {
            char c;
            cin >> c;
            if (c == 'C')
            {
                int x = gi(), y = gi(), xx = gi(), yy = gi();
                add(x, y), add(xx + 1, y), add(x, yy + 1), add(xx + 1, yy + 1);//进行插入操作
            }
            else 
            {
                int x = gi(), y = gi();
                printf("%d\n", getans(x, y) % 2);//输出最终答案
            }
        }
    }
    return 0;//结束
}

猜你喜欢

转载自www.cnblogs.com/xsl19/p/11139626.html