poj2155 Matrix(經典二維樹狀陣列)
阿新 • • 發佈:2019-02-15
吐槽:這題先說[x1,y1]和[x2,y2]是左上角和右下角的兩個點,又說x1<=x2&&y1<=y2,那就是x軸向右,y軸向下為正方向。mdzz啊,座標系這種東西能不能標準一下= =,這裡我們就按照左下角和右上角來了。
題意:輸入n*n矩陣,有兩個操作,C代表翻轉[x1,y1]到[x2,y2]矩陣內的值(0變1,1變0),Q代表查詢某點的值。
思路:和普通的單點更新和求和不同,這裡是區間更新和單點求值。重點在於翻轉操作,矩陣大操作多肯定不能一個一個翻。看懂這個是關鍵。
這篇部落格把二進位制中的區間更新變為了邊界更改,也是二進位制所特有的,剛開始死活看不懂,這nmsjbwya,後來紙上模擬一下,什麼都懂了。
某點的翻轉次數變為了求1~x的和,二進位制中對邊界的更改體現到了區間上,然後模2得出值。只能說我表達不清,絕知此事要躬行吧= =
#include <stdio.h> #include <algorithm> #include <string.h> #include <math.h> using namespace std; typedef long long ll; const int N = 1005; int tree[N][N], n;//從當前元素開始連續往左求lowbit(x)個數的和 int lowbit(int x) { return -x&x; } void update(int i, int j, int val) { while(i <= n) { int tmp = j; while(tmp <= n) { tree[i][tmp]+=val; tmp+=lowbit(tmp); } i+=lowbit(i); } } int sum(int i, int j) { int num = 0; while(i > 0)//說明還有組可加 { int tmp = j; while(tmp > 0) { num+=tree[i][tmp]; tmp-=lowbit(tmp); } i-=lowbit(i); } return num; } int main() { // freopen("in.txt", "r", stdin); int X, t, x, y, x1, y1, x2, y2, flag = 0; char op[5]; scanf("%d", &X); while(X--) { if(flag) printf("\n"); flag = 1; scanf("%d%d", &n, &t); memset(tree, 0, sizeof(tree)); for(int i = 1; i <= t; i++) { scanf("%s", op); if(op[0] == 'C') { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); update(x1, y1, 1); update(x1, y2+1, 1); update(x2+1, y1, 1); update(x2+1, y2+1, 1); } else if(op[0] == 'Q') { scanf("%d%d", &x, &y); printf("%d\n", sum(x, y)%2);//從[1,1]到該點的和 } } } return 0; }