二维树状数组

回顾一维树状数组

初始化、求和

c1 = a1;
c2 = a1 + a2;
c3 = a3;
c4 = a1 + a2 + a3 + a4;
c5 = a5;
c6 = a5 + a6;
……
C16 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + 13 + a14 + a15 + a16;
求和:

int sum (int c[], int n)
{
    int sum = 0;
    while(n > 0)
    {
        sum += c[n];
        n -= lowbit(n);
    }
}

解释一下上面:假设n = 16那么c[16]代表的就是前16项的和,而 16 -= lowbit(16) = 0;所以循环结束。

更改数值

int change (int i, int x, int n) // i表示更改的位置, x表示改为的数。
{
    while(i <= n)
    {
        c[i] += x;
        i += lowbit(i);
    }
}

二维树状数组

提出问题

一个由数字构成的大矩阵,能进行两种操作
1) 对矩阵里的某个数加上一个整数(可正可负)
2) 查询某个子矩阵里所有数字的和,要求对每次查询,输出结果。

二维树状数组介绍

一维数组很容易扩展到2维

假设在2维的情况下原始的数据定义为A[][]

那么树状数组就可以定义为C[x][y] = ΣA[i][j]

其中 x - lowbit(x) < i < x; ··········y - lowbit(y) < j < y;

下面我们举个例子:

假设原始的二维数组是:

A[][]={{a11,a12,a13,a14,a15,a16,a17,a18,a19},
{a21,a22,a23,a24,a25,a26,a27,a28,a29},
{a31,a32,a33,a34,a35,a36,a37,a38,a39},
{a41,a42,a43,a44,a45,a46,a47,a48,a49}};

为了好理解我们引入中间数组B[][]

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] 表示为c11 以此类推

c11 = a11; c12 = a11 + a12 ; c13 = a13 ; c14 = a11 + a12 + a13 +
a14; c15 = a15………………

c21 = a11 + a21; c22 = a11 + a12 + a22 + a21; c23 = a13 + a23;
C24=a11+a12+a13+a14+a21+a22+a23+a24

c31 = a31; c32= a31 + a32; c33 = a33; c34 = a31 + a32 + a33 + a34;c35
= a35;

c41 = a11 + a21 + a31 + a41; c42 = a11 +a12 + a21 + a22 + a31 + a32 +
a41 + a42;

以上找规律:

我们发现C中的第一个数字表示的是树状数组在纵向上的个数, 第二个数字表示在横向上的个数(也就是一维树状数组)

讲到这二维数组的定义基本讲完,我们返回前面的两道例题

求和

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

和一维的完全一样只是加了一个for循环

改变数值

private void Modify(int i, int j, int n, int m, int delta)
{

         A[i][j]+=delta;

       for(int x = i; x< n; x += lowbit(x))
        for(int y = j; y < m; y += lowbit(y))
        {
          C[x][y] += delta;

        }
}

你可能感兴趣的:(树状数组)