关键词:树状数组
二维树状数组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(" %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 ", QueryX(x1, y1)); break; default: assert(0); } } printf(" "); } return 0; }