POJ-2155(二維樹狀陣列)
阿新 • • 發佈:2019-01-30
學習了這篇部落格的講解徹底弄懂二維樹狀陣列,做了二維樹狀陣列的第1題。
雖然是二維,但跟一維的思想基本相同,只不過一維時用C[i]表示a[i-lowbit[i]+1] ~ a[i]的和,二維時用c[i][j]表示a[i-lowbit[i]+1][j-lowbit[j]+1] ~ a[i][j]的和。
先來看一維的問題,則矩陣退化成線段,(x,y)點退化成x點,操作也變為C x y和Q x:
(1)對於C x y,即對[x,y]之間的所有點翻轉,相當於對[1,x-1]之間的所有點翻轉,再對[1,y]之間的所有點翻轉
(2)對於Q x,即查詢點x進行了多少次翻轉,由於y = x,y = y+lowbit(y),y = y+lowbit(y)都覆蓋了點x,所以我們只需對這些c[y]累加,即可得到x點的翻轉次數
將上述思想推廣到二維,則
(1)對於C a b c d,即對[a,b] -> [c,d]之間的所有點進行翻轉,相當於對[1,1] -> [a-1,d]之間的所有點進行翻轉,再對[1,1] -> [c,b-1]之間的所有點進行翻轉,再對[1,1] -> [a-1,b-1]之間的所有點進行翻轉,在對[1,1] -> [c,d]之間的所有點進行翻轉
(2)對於Q a b,即查詢點(a,b)進行了多少次翻轉,由於[x = a; y = b, y = y + lowbit(y), ... y = y + lowbit(y)]覆蓋了點(a,b),且[x = x + lowbit(x); y = b, y = y + lowbit(y), ..., y = y + lowbit(y)]覆蓋了點(a,b),以此類推。
#include <cstdio> #include <cstring> #define MAX 1024 int N, T, c[MAX][MAX] = {0}; inline int lowbit(int x){ return x & -x; } void init() { for(int i = 1; i <= N; ++i) memset(c[i] + 1, 0, N * sizeof(int)); } void update(int i, int j) { for(int x = i; x; x -= lowbit(x)) for(int y = j; y; y -= lowbit(y)) ++c[x][y]; } int query(int i, int j) { int sum = 0; for(int x = i; x <= N; x += lowbit(x)) for(int y = j; y <= N; y += lowbit(y)) sum += c[x][y]; return sum; } int main() { int test, a, b, c, d; char s[4]; for(scanf("%d", &test); test--; ){ scanf("%d%d", &N, &T); init(); while(T--){ scanf("%s%d%d", s, &a, &b); if(s[0] == 'C'){ scanf("%d%d", &c, &d); update(c, b-1); update(a-1, d); update(a-1, b-1); update(c, d); } else puts(query(a, b) & 1 ? "1" : "0"); } puts(""); } return 0; }