POJ 2155 Matrix(二维树状数组)


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


题意:操作C表示让左上角为(x1,y1)右下角为(x2,y2)的矩形内所有的01取反,一开始的时候全部为0。Q询问(x,y)内是0还是1。


这道题可以把01取反看成是操作C的累加,如果某个单元被操作了奇数次,那么相当于取反,否则就是没有动。这道题和一维情况中改变区间查询点的情况类似,只是将一维升级成二维。如果现在要改变左上角为(x1,y1)右下角为(x2,y2)的矩形,那么只要给一个二维数组中(x1,y1)(x2+1,y2+1)(x1,y2+1)(x1+1,y2)全部加上1,以(x1,y1)为例,在查询(x,y)的时候,通过累加,会把以(1,1)为左上角,(x,y)为右下角的矩形中所有的数加起来,那么如果(x1,y1)在这范围内,对(x,y)而言,就被操作了一次。综合起来,就是把以(x1,y1)为左上角,(n,n)为右下角的矩形内01取反。同理,其他也是一样的。最后相互抵消后,相当于是让左上角为(x1,y1)右下角为(x2,y2)的矩形内所有的01取反。



#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1005
using namespace std;
int n;
char s[3];
int c[N][N];
int lowbit(int x)
{
    return x&(-x);
}
void change(int x, int y, int d)
{
    int i = y;
    while(x <= n)
    {
        y = i;
        while(y <= n)
        {
            c[x][y] += d;
            c[x][y] %= 2;
            y += lowbit(y);
        }
        x += lowbit(x);
    }
}
int query(int x, int y)
{
    int i = y, sum = 0;
    while(x > 0)
    {
        y = i;
        while(y > 0)
        {
            sum += c[x][y];
            sum %= 2;
            y -= lowbit(y);
        }
        x -= lowbit(x);
    }
    return sum;
}
int main()
{
    int T, m, ans, x, y, x2, y2, x1, y1;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= m; i++)
        {
            scanf("%s", &s);
            if (s[0] == 'C')
            {
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                change(x2+1, y2+1, 1);
                change(x1, y2+1, 1);
                change(x2+1, y1, 1);
                change(x1, y1, 1);
            }
            if (s[0] == 'Q')
            {
                scanf("%d%d", &x, &y);
                ans = query(x, y);
                printf("%d\n", ans);
            }
        }
        if (T) printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值