一、树状数组


树状数组可以在logn的时间内求出一段连续区间的和,特别对于多次修改后再求值,树状数组就显得尤为重要了。

for(int i=x;i<=maxn;i+=lowbit(i))
{
	C[i]+=val;
}


求和:


和第i项有关的项都在前面,所以求和操作就是
for(int i=x;i;i-=lowbit(i))
{
    ans+=tree[i];
}

比如求前11项的和,转换为C[11]+C[10]+C[8],这样就不会漏项了。


注意:


树状数组一定从第一项开始,所以在做题的时候一样要注意原数组的开始位置。


二、二维树状数组

给定一个矩阵,然后会修改某个值,再问你某个子矩阵的和

其实也很容易,同样的定义一个树状数组C[][]

则有:

感想——树状数组和二维树状数组_数组


其实就是行和列上都来一次树状数组,对于第i行的,根据lowbit(i)包含前面的项,对于第j列的,其实和一维树状数组一样了。

更新:

  

void add(int x,int y)
{
    for (int i=x;i<=N;i+=lowbit(i))
        for (int j=y;j<=N;j+=lowbit(j))
            C[i][j]++;



求和:

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




感想


巧妙地利用树状数组,可以解决很多问题,而且其效率也很高,是一种很神奇的数据结构,树状数组灵活多变,个人认为活学活用还是挺有难度的......多做题,争取提高这方面的能力吧!