POJ2155 Matrix 二维树状数组

关键词:树状数组

二维树状数组C中,X树状数组维护一个Y树状数组,C[x][y]表示点(1,1)至点(x,y)是否被翻转过。先操作X数组,再操作每个X所维护的Y数组。

注意:反转(x1,y1):(x2,y2)时,反转了(x2,y2)的前缀和(x1-1,y1-1)的前缀就行了?不!还要把(x1-1,y2)和(x2, y1-1)的前缀再反转一遍。否则以上不该反转部分就被多反转了一次。

#include <cstdio>
#include <cstring>
#include <cassert>
using namespace std;

const int MAX_N = 1010;
bool C[MAX_N][MAX_N];
int N;

int Lowbit(int i)
{
    return i&(-i);
}

void ModifyY(int x, int y)
{
    while (y)
    {
        C[x][y] ^= 1;
        y -= Lowbit(y);
    }
}

bool QueryY(int x, int y)
{
    bool ans = 0;
    while (y <= N)
    {
        ans ^= C[x][y];
        y += Lowbit(y);
    }
    return ans;
}

void ModifyX(int x, int y)
{
    while (x)
    {
        ModifyY(x, y);
        x -= Lowbit(x);
    }
}

bool QueryX(int x, int y)
{
    bool ans = 0;
    while (x <= N)
    {
        ans ^= QueryY(x, y);
        x += Lowbit(x);
    }
    return ans;
}

void Init(int n)
{
    memset(C, 0, sizeof(C));
    N = n;
}

int main()
{
#ifdef _DEBUG
    freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
    int caseCnt, mSize, opCnt, x1, x2, y1, y2;
    char op;
    scanf("%d", &caseCnt);
    while (caseCnt--)
    {
        scanf("%d%d", &mSize, &opCnt);
        Init(mSize);
        while (opCnt--)
        {
            scanf("\n%c", &op);
            switch (op)
            {
            case 'C':
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                ModifyX(x2, y2);
                ModifyX(x1 - 1, y2);
                ModifyX(x2, y1 - 1);
                ModifyX(x1 - 1, y1 - 1);
                break;
            case 'Q':
                scanf("%d%d", &x1, &y1);
                printf("%d\n", QueryX(x1, y1));
                break;
            default:
                assert(0);
            }
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-02-13 09:47  headboy2002  阅读(191)  评论(0编辑  收藏  举报