【树状数组】知识汇总

一、资源汇总

树状数组是每一个ACMer都必备的高级数据结构,第一次接触是在刘汝佳的胖白书(p194)中,其实网上也有不少优秀的blog

1.topcoder:点击打开链接

2.题目归类的blog:点击打开链接

3.多维的树状数组:点击打开链接

4.题目解析:点击打开链接


二、基本概述

三剑客:

int lowbit(int x){
    return x & (-x);

}
int sum(int x){
    int ret = 0;
    while (x>0){
        ret += c[x];x -= lowbit(x);
    }
    return ret;
}

void add(int x,int d){
    while(x<=n){
        c[x] += d; x += lowbit(x);
    }
}
四、证明方式

树状数组的灵感是来源于二进制、线段树和O(1)查询O(n)修改算法(其实是我自己的灵感啦哈哈),二进制有01组成,每一个数字都有自己对应的一个二进制,既然线段数是把数据按二分的思想,把区间分成两个一样大小的区间,把大问题分解成两个小的子问题,那么在一组规模大小是10010110的数据,同样的我们也可以把区间分成一个个子区间,把大问题分解成一个个小问题,那么要怎么分解呢?看这二进制就明白了,我们要把区间分解成一个个大小不一的子区间,使它们加起来刚好就是原来的区间,很明显这个二进制可以分成:

如果我们要求1到10010100的和,即可用四个子区间组成原问题
[1,10]
[11,100]
[1001,10000]
[10001,10010100]
把它们加起来就是了,这就是说我们每次都把10010110最右边的“1”拿出来,作为子区间的右边界,左边界就是前一个子区间的右边界加1,第一个子区间的左边界是1.用位运算,把最右边的1分解,i&(i^(i-1))即i&(-i),这是自低向上的把区间分解出来,接下来就是定义tree[i]来递推了,按照上面的分法,很难定义,所以我们自顶向下的分区间试试看能不能容易的定义,分的四个区间:
[10010101,10010110]
[10010001,10010100]   
[10000001,10010000]
[00000001,10000000]
这样定义起来就很方便了,我們可以看到右區間就是每往下都去掉一個最右邊的1,tree[i]就是区间[i-(i&-i)+1,i]的和,由这里的定义知道,树状数组要从1开始计数



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值