poj 2155 Matrix 二维树状数组 (经典)

/**
*   这题太经典了!
*   二维树状数组:
*      要是对二维树状数组理解的不够是会完全想错的。
*   首先,树状数组也好,二维树状数组也好,update(int x) 一定是对数组或者二维数组
*   的维护,是在数组某个点上加上一个数后再对数组的维护! 而get_sum(int x, int y)是对二维区间
*   的求和操作。
*      而这题正好相反! 题意是改变区域内的值和求某个点的值!千万不要理解错了。。。(开始我就这么理解,一直在死胡同里绕啊绕。T^T)
*   准确理解完后,就是考虑如何运用二维树状数组解这题了,其实就是要在一个二维区间里的某几个点做标记(加一)
*   能够正确表示被置反的区间。
*   具体的: http://blog.csdn.net/zxy_snow/article/details/6264135  (非常详细,顺便膜拜下)
*/

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#define INF 0x7fffffff
#define MAXS 1001
#define LL long long
using namespace std;
int c[MAXS][MAXS];
int n;

int lowbit(int x) {
    return x & (-x);
}

void update(int x, int y, int d) {
    if(x <= 0 || y <= 0) return ;
    for(int i = y; i <= n; i += lowbit(i)) {
        for(int j = x; j <= n; j += lowbit(j))
            c[i][j] += d;
    }
}

int get_sum(int x, int y) {
    if(x <= 0 || y <= 0) return 0;
    int ret = 0;
    for(int i = y; i > 0; i -= lowbit(i)) {
        for(int j = x; j > 0; j -= lowbit(j))
            ret += c[i][j];
    }
    return ret;
}

void init(int n) {
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            c[i][j] = 0;
}

int main()
{
    int t, num;
    scanf("%d", &t);
    while(t -- ) {
        scanf("%d%d", &n, &num);
        init(n);
        while(num --) {
            getchar();
            char cmd = getchar();
            if(cmd == 'C') {
                int x1, x2, y1, y2;
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                x1 ++, x2 ++, y1 ++ , y2 ++;
                update(x2, y2, 1);
                update(x1 - 1, y2, 1);
                update(x2, y1 - 1, 1);
                update(x1 - 1, y1 - 1, 1);
            } else if(cmd == 'Q') {
                int x, y, ans;
                scanf("%d%d", &x, &y);
                ans = get_sum(x, y);
                ans %= 2;
                printf("%d\n", ans);
            }
        }
        if(t) printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值