1.前缀和
一维:就是数组y是数组x前面所有数字的和
2.树状数组(一维)
前缀和在更新的时候,对应的数字都要更新,十分复杂,所以引入树状数组。还是之前那个数组,只不过元素之间的逻辑关系不是直线,而是树的样子
特点:
c的项数 == 数字二进制最低位1所代表的数字
// 求最低位1方法
int lowbit(x) //简单写法,还有一种复杂一点的,不管~
{
return x & -x ;
}
更新操作
查询操作
题目
3.树状数组(二维)
在一维树状数组中,tree[x](树状数组中的那个“数组”)记录的是右端点为x、长度为lowbit(x)的区间的区间和。
那么在二维树状数组中,可以类似地定义tree[x][y]记录的是右下角为(x, y),高为lowbit(x), 宽为 lowbit(y)的区间的区间和。
设原始二维数组为:
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},
};
先对每一行,用树状数组建立
第一行:B[1]={a11, a11+a12, a13, a11+a12+a13+a14, a15, a15+a16,…}
第二行:B[2]={a21, a21+a22,a23, a21+a22+a23+a24, a25, a25+a26,…}
第三行:B[3]={a31, a31+a32, a33, a31+a32+a33+a34, a35, a35+a36,…}
第四行:B[4]={a41, a41+a42, a43, a41+a42+a43+a44, a45, a45+a46,…}
再对每一列,用树状数组建立
第一行二维树状数组 == 第一行
C[1][1]=a11,C[1][2]=a11+a12,C[1][3]=a13,C[1][4]=a11+a12+a13+a14,c[1][5]=a15,C[1][6]=a15+a16,…
第二行二维树状数组 == 第一行+第二行
C[2][1]=a11+a21,C[2][2]=a11+a12+a21+a22,C[2][3]=a13+a23,C[2][4]=a11+a12+a13+a14+a21+a22+a23+a24,
C[2][5]=a15+a25,C[2][6]=a15+a16+a25+a26,…
第三行二维树状数组 == 第三行
C[3][1]=a31,C[3][2]=a31+a32,C[3][3]=a33,C[3][4]=a31+a32+a33+a34,C[3][5]=a35,C[3][6]=a35+a36,…
第四行二维树状数组 == 第一行+第二行+第三行+第四行
C[4][1]=a11+a21+a31+a41,C[4][2]=a11+a12+a21+a22+a31+a32+a41+a42,C[4][3]=a13+a23+a33+a43,…
int lowbit(int x)
{
return x & (-x);
}
void update(int x, int y, int a)
{
for(int i=x;i<=s;i+=lowbit(i))
for(int j=y;j<=s;j+=lowbit(j))
map[i][j]+=a;
}
int add(int x, int y) //从(1,1)到(x,y)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
for(int j=y;j>0;j-=lowbit(j))
sum+=map[i][j];
return sum;
}
题目
4.差分
数组中记录的是每个元素与上一个元素的差值
利用前缀和实现单点查询
当区间修改的时候,给区间
[
l
,
r
]
[l,r]
[l,r]加上k时,a[l]比a[l-1]多了k,a[r]比a[r+1]少了k,只需要操作两端的值即可