POJ-2155(二维树状数组)

来源:互联网 发布:淘宝展现量怎么算 编辑:程序博客网 时间:2024/06/04 23:21

题目:http://poj.org/problem?id=2155

学习了这篇博客的讲解彻底弄懂二维树状数组,做了二维树状数组的第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 1024int 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;}


0 0
原创粉丝点击