一维及二维数状数组模板

以前看树状数组总觉得很难,到现在看回来其实本质不过是一个简单的高校维护前缀和的小工具,也不必掌握差分,区间修改老老实实用线段数会比较直观。

两个要注意的地方

  • 数组下标要从一开始
  • 数状数组适用于一切满足结合律的运算 如乘法、加法、异或
    奉上我的数状数组板子

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

#include 
#define rep(i, a, b) for (int i=a; i<=b; i++)
#define drep(i, a, b) for (int i=b; i>=a; i--)
typedef long long ll;
using namespace std;
const int maxn=1010;
struct BIT {
    int a[maxn][maxn];
    inline int lowbit(int x) {
        return x & (-x);
    }
    void init() {
        for (int i=0; imemset(a[i], 0, sizeof(a[i]));
    }
    /*一维数状数组,init函数自行修改一下即可
    void modify(int x,int add) {
        while (x <= n) {
            a[x] += add;
            x += lowbit(x);
        }
    }
    int get_sum(int x) {
        int ret = 0;
        while (x != 0) {
            ret += a[x];
            x -= lowbit(x);
        }
        return ret;
    }
    */

    void modify(int x, int y, int data) {
        for (int i = x; i < maxn; i += lowbit(i))
            for (int j = y; j < maxn; j += lowbit(j))
                a[i][j] += data;
    }

    int query(int x, int y) {
        int res = 0;
        for (int i = x; i > 0; i -= lowbit(i))
            for (int j = y; j > 0; j -= lowbit(j))
                res += a[i][j];
        return res;
    }
}s;
int main() {
    int test, x1, y1, x2, y2, n , m;
    char str[4];
    for(scanf("%d", &test); test--; ){
        scanf("%d%d", &n, &m);
        s.init();
        while(m--){
            scanf("%s%d%d", str, &x1, &y1);
            if(str[0] == 'C'){
                scanf("%d%d", &x2, &y2);
                x1++; y1++; x2++; y2++;
                s.modify(x2, y1-1, 1);
                s.modify(x1-1, y2, 1);
                s.modify(x1-1, y1-1, 1);
                s.modify(x2, y2, 1);
            }
            else puts(s.query(x1, y1) & 1 ?  "1" : "0");
        }
        puts("");
    }
    return 0;

}

你可能感兴趣的:(acm)