树状数组模板

来源:互联网 发布:单片机是什么专业学的 编辑:程序博客网 时间:2024/06/05 09:31

树状数组还可以用来求区间异或和等与加法相同性质的操作

单点更新, 区间查询

相比于线段树, 好写的多
下标从1开始, sum(k)返回区间[1, k]的值, update将位置p的值+x
复杂度都是O(logn)

int bit[maxn], n;inline int lowbit(int x) { return x&(-x); }inline void init(int n) { memset(bit, 0, sizeof(int) * (n+1)); }int sum(int k){    return k<=0 ? 0 : bit[k] + sum(k-lowbit(k));}void update(int p, int x){    for( ; p<=n; p+=lowbit(p)) bit[p] += x;}inline int query(int l, int r) { return sum(r) - sum(l-1); }

区间寻该, 单点查询

核心代码一模一样, 只是调用函数时候不同

int bit[maxn], n;inline int lowbit(int x) { return x&(-x); }inline void init(int n) { memset(bit, 0, sizeof(int) * (n+1)); }int sum(int k){    return k<=0 ? 0 : bit[k] + sum(k-lowbit(k));}void update(int p, int x){    for( ; p<=n; p+=lowbit(p)) bit[p] += x;}//将区间[l, r]加vupdate(l, v);update(r+1, -v);//查询点possum(pos);

区间修改, 区间更新

利用一个二维树状数组实现区间更新, 复杂度都是O(logn)

int bit0[MAXN], bit1[MAXN];int n;inline int lowbit(int x) { return x&(-x); }int sum(int bit[], int k){    return k<=0 ? 0 : bit[k] + sum(bit, k - lowbit(k));}void update(int bit[], int i, int x){    for( ; i<=n; i+=lowbit(i)) bit[i] += x;}inline int query(int l, int r){    return sum(bit0, r) - sum(bit0, l-1) + sum(bit1, r) * r - sum(bit1, l-1) * (l-1);}inline void update(int l, int r, int x){    update(bit0, l, -x*(l-1));    update(bit0, r+1, x*r);    update(bit1, l, x);    update(bit1, r+1, -x);}

二维树状数组

单点更新, 区间查询

const int maxn = 2500 + 10, inf = 0x3f3f3f3f;typedef unsigned long long ull;ull bit[maxn][maxn];int n;inline int lowbit(int x) { return x&(-x); }ull sum(int x, int y){    ull s = 0;    for(int i=x; i>0; i-=lowbit(i))        for(int j=y; j>0; j-=lowbit(j))            s += bit[i][j];    return s;}void add(int x, int y, int v){    for(int i=x; i<=maxn; i+=lowbit(i))        for(int j=y; j<=maxn; j+=lowbit(j))            bit[i][j] += v;}//查询(x1, y1), (x2, y2)sum(x2, y2)-sum(x2, y1-1)-sum(x1-1 ,y2)+sum(x1-1, y1-1);//修改(x,y)add(x, y, v);

区间修改, 单点查询

//查询(x, y)sum(x, y);//改变(x1, y1)(x2, y2)全部加vadd(x1, y1, v);add(x1, y2+1, -v);add(x2+1, y1, -v);add(x2+1, y2+1, v);
原创粉丝点击