poj2155 Matrix(二维线段树)

http://poj.org/problem?id=2155

Matrix
Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 12894Accepted: 4834

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
题目大意:
给一个N*N的矩阵,每次给一个命令取反一个子矩阵,或者查询其中某一点的01状态。(注意每两组output中间要空行,PE了一次)

解题方法;
二维线段树。

 

二维线段树确实不会用,而且理解的不深啊。。。。

解题小结:
原先好像写过二维的线段树,不过都忘得差不多了,这一次算是重新捡起来吧。
这一道题可以用a[rootx][rooty]来记录rootx段到rooty段是否取反,rootx指向行里的一段,rooty指向列里的一段,那么[rootx][rooty]就自然是一个子矩阵了。
最后求(x,y)是否取反,就是一路遍历所有包含x,y的矩阵,记录一下一共取反了多少次(Discuss里说用异或,很不错哈~)
这一题更新和查询都写成x,y版本的,x版本套y版本,就解二维的问题了。
例如在Modify_x里套用Modify_y。

#include
#include
#include
#define maxn 1010
int a[4*maxn][4*maxn];
int ans;

void Modify_y(int rootx, int rooty, int l, int r, int y1, int y2)
{
    if (y1==l && y2==r)
 {
        a[rootx][rooty]=!a[rootx][rooty];
    }
    else
 {
        int mid=(l+r)>>1;
       if (y2<=mid)
           Modify_y(rootx, (rooty<<1), l, mid, y1, y2);
       else if (y1>mid)
            Modify_y(rootx, (rooty<<1)+1, mid+1, r, y1, y2);
        else
  {
           Modify_y(rootx, (rooty<<1), l, mid, y1, mid);
            Modify_y(rootx, (rooty<<1)+1, mid+1, r, mid+1, y2);
        }
    }
}

void Modify_x(int rootx, int n, int l, int r, int x1, int x2, int y1, int y2)
{
    if (x1==l && x2==r)
 {
        Modify_y(rootx, 1, 1, n, y1, y2);
    }
    else
 {
       int mid=(l+r)>>1;
      
       if (x2<=mid)
            Modify_x((rootx<<1), n, l, mid, x1, x2, y1, y2);
        else if (x1>mid)
           Modify_x((rootx<<1)+1, n, mid+1, r, x1, x2, y1, y2);
        else
  {
            Modify_x((rootx<<1), n, l, mid, x1, mid, y1, y2);
            Modify_x((rootx<<1)+1, n, mid+1, r, mid+1, x2, y1, y2);
        }
    }
}

void Query_y(int rootx, int rooty, int l, int r, int y)
{
   ans^=a[rootx][rooty];
    if (l
 {
        int mid=(l+r)>>1;
        if (y<=mid)
           Query_y(rootx, (rooty<<1), l, mid, y);
        else
            Query_y(rootx, (rooty<<1)+1, mid+1, r, y);
    }
}

void Query_x(int rootx, int n, int l, int r, int x, int y)
{
    Query_y(rootx, 1, 1, n, y);
    if (l
        int mid=(l+r)>>1;
        if (x<=mid)
            Query_x((rootx<<1), n, l, mid, x, y);
       else
           Query_x((rootx<<1)+1, n, mid+1, r, x, y);
    }
}

int main()
{
    int cases, n, t, x1, x2, y1, y2;
    char ch[5];
    scanf("%d", &cases);
    for (int cs=1; cs<=cases; cs++)
 {
        if (cs!=1) printf("\n");
       scanf("%d%d", &n, &t);
        memset(a, 0, sizeof(a));
       while (t--)
    {
     scanf("%s", ch);
            if (ch[0]=='C')
   {
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                Modify_x(1, n, 1, n, x1, x2, y1, y2);
           }
            else
   {
                ans=0;
                scanf("%d%d", &x1, &y1);
                Query_x(1, n, 1, n, x1, y1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值