一维 + 二维树状数组 + 单点更新 + 区间更新 详解

树状数组详解:

假设一维数组为A[i](i=1,2,...n),则与它对应的树状数组C[i](i=1,2,...n)是这样定义的:

C1 = A1

C2 = A1 + A2

C3 = A3

C4 = A1 + A2 + A3 + A4

C5 = A5

C6 = A5 + A6

.................

C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

................

如图可知:

为奇数的时候他是代表他本身,而为偶数的时候则是代表着自己以及属于它管辖区域的和。

(1)C[x] 展开以后有多少项?由下面公式计算:

int lowbit(int x) { //计算 C[x] 展开的项数
    return x & (-x);
}

得到了项数后x - lowbit(x),得到的即使前一区域的x

举个例子:

如果x = 6, x - lowbit(x) == 4 即为C[4]如此,此处说明x & (-x)的作用是求x转换为二进制时最后一个1的位置在哪里,至于为什么,这就是树状数组的神奇之处,一个非常牛逼的规律

然后更新单点的模板代码就成型:

void add(int pos, int c){
    while(pos <= n){
        C[pos] += c;
        pos += lowbit(pos);//转移到他的父亲节点,如果这个点更新C[4],那么下一个更新的点就是C[8],相当于他的父亲
    }
}

求和代码也已经成型:

int sum(int pos){
    int ret = 0;
    while(pos > 0){
        ret += C[pos];
        pos -= lowbit(pos);//当你要计算1..6的和时,结果即为C[4] + C[6]
    }
}

如果是二维的树状数组的话,心里思考一下,是不是感觉很眼熟哦!

其实他们的原理是一样的:

设二维数组为:

  a[][]={{a11,a12,a13,a14,a15,a16,a17,a18},

{a21,a22,a23,a24,a25,a26,a27,a28},

{a31,a32,a33,a34,a35,a36,a37,a38},

{a41,a42,a43,a44,a45,a46,a47,a48}};

那么C[1][1] = a11,C[1][2] = a11 + a12;

如此当C[1][i]...C[1][j]时跟一维的树状数组是没有什么区别的

那么C[2][1] = a11 + a21,C[2][2] = a11 + a12 + a21 + a21,如此可以发现

其实C[2][i].....C[2][j],就是C[1][],C[2][],单独的两个一维树状数组同一位置的值合并在一起

C[3][1] = a31,C[3][2] = a31 + a32......

C[4][1] = a11 + a21 + a31 + a41,C[4][2] = a11 + a12 + a21 + a22 + a31 + a32 + a41 + a42

有没有发现,如果单独把二维中的第一个维度拿出来A[1][m] + A[2][m] = C[2][m],A[3][m] = C[3][m],

是不是也和一维的数组一样,所以二维数组的规律就是,不管是横坐标还是纵坐标,将他们单独拿出来,他们

都符合x += lowbit(x),属于它的父亲节点.

如此二维数组的单点更新代码如下:

void add(int x, int y, int c){
//如果我改变了C[x][y]这个点,那么接下来C[x][y += lowbit(y)]当做一维数组的话都是要改变一个c的
//接着我们的纵坐标也是要改变的C[x += lowbit(x)][y]也是要改变的,应为他们都包含了C[x][y]这个集合
    for(int i = x;i < n;i += lowbit(i)){
        for(int j = y; j < n;j += lowbit(j)){
            C[i][j] += c;
        }
    }
}

那么求和代码就更加好办了

int sum(int x,int y){
    int ret = 0;
    for(int i = x; i > 0; i -= lowbit(i)){
        for(int j = y;j > 0;j -= lowbit(i)){
            ret += C[i][j];
        }
    }
    return ret;
}

这就是二维树状数组的成型,那么三维以及以上呢,想来大家都已经秒懂了,是的,没错,就是在最外一层加个循环跟一维变为二维原理一样

而对于区间增加以及减少依旧很简答

比如举个例子,我要将[x, y]区间增加d,那么可以先将1....y加上d,然后1.....x减去d

对于二维树状数组的区间更新也是如此

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 03:42:43

一维 + 二维树状数组 + 单点更新 + 区间更新 详解的相关文章

POJ 2155 Matrix【二维树状数组+YY(区间更新,单点查询)】

题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 32950   Accepted: 11943 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th col

TOJ 2725 See you~(二维树状数组单点更新区间查询)

描述 Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algorithm and Programming, and I met so many good friends. I want to say sorry to Mr, Yin, I must leave now ~~>.<~~. I am very sorry, we could not advanc

POJ2155 Matrix 【二维树状数组】+【段更新点查询】

Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17766   Accepted: 6674 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1

【2018年全国多校算法寒假训练营练习比赛(第五场)-E】情人节的电灯泡(二维树状数组单点更新+区间查询)

试题链接:https://www.nowcoder.com/acm/contest/77/E 题目描述 情人节到了,小芳和小明手牵手,打算过一个完美的情人节,但是小刚偏偏也来了,当了一个明晃晃的电灯泡,小明很尴尬,就和小刚说,我交给你个任务,你完成了我俩就带你玩,否则你就回家吧.小刚很有当单身狗的觉悟,他坚决不想让小明过好情人节,同为单身狗的你能帮帮他吗?现在有一个n×n(1 <= n <= 1000)的格子,每一个格子都有一个电灯泡,可能是亮的,也可能是灭的(1代表亮, 0代表灭),现在有两

学习笔记——二维树状数组

不知道为什么,就是想把这个坑给填了... 二维树状数组,本质上还是树状数组,只是在一维的基础上变成了二维... 单点修改  1到i,j查询和一维基本一样,直接上代码 #include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> #define N 3010 using namespace std; int a[N][N],n; inline int lowbit(int x

【poj1195】Mobile phones(二维树状数组)

题目链接:http://poj.org/problem?id=1195 [题意] 给出一个全0的矩阵,然后一些操作 0 S:初始化矩阵,维数是S*S,值全为0,这个操作只有最开始出现一次 1 X Y A:对于矩阵的X,Y坐标增加A 2 L B R T:询问(L,B)到(R,T)区间内值的总和 3:结束对这个矩阵的操作 [思路] 二维树状数组单点更新+区域查询,可作为模板题. 注意坐标是从0开始,所以要+1 [代码] 1 #include<cstdio> 2 #include<cstrin

POJ 1195-Mobile phones(二维树状数组-区间更新区间查询)

Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17661   Accepted: 8173 Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The

POJ 1195 Mobile phones(二维树状数组)

题目链接:POJ 1195 题意: 给出一个S*S的矩阵(行.列号从1开始),每个元素初始值为0,有两种操作:一种是第X行第Y列元素值加A:另一种是查询给定范围矩阵的所有元素之和(L<=X<=R,B<=Y<=T). 分析: 查询给定范围矩阵的所有元素之和是二维区间和,可以转换为二维前缀和求值.类比一维前缀和求法,二维区间和S(L, B, R, T) = S(1, 1, R, T) - S(1 ,1, L-1, T) - S(1, 1, R, B-1) + S(1, 1, L-1,

2018年四校联合周赛-第二场 B.异或和问题(二维树状数组)

异或和问题 TimeLimit:1000MS  MemoryLimit:256MB 64-bit integer IO format:%I64d Problem Description 现在有一个n行n列的矩阵.初始状态下,矩阵里的所有值都为0.行的编码是从1到n,列的编码也同样是从1到n. ai,?j.是在第i行第j列的数.子矩阵(x0, y0, x1, y1)是由ai,?j. (x0?≤?i?≤?x1, y0?≤?j?≤?y1)组成的矩阵. 现在需要进行下列的两个操作:       1.查询