[数据结构].树状数组

树状数组

定义

即二叉索引树或Fenwick树,支持动态单节点修改与连续和查询。

操作

  • 建树(Ο(NlogN))
  • 查询前缀和(Ο(logN))
  • 单节点修改(Ο(logN))

C++实现

先定义函数
lowbit(x)=x&-x
它代表x的二进制表达式中从最右边的1开始的数所对应的二进制值,如38288的二进制为10010101100 10000
加粗部分即为所对应的二进制值,故lowbit(38288)=16
函数定义时用位运算与补码简化了计算。


定义这个函数是为了形成以下的树状结构:这里写图片描述

将一根根白条(包括灰节点)囊括节点的总和保存在灰色节点,如12对应的灰色节点储存9~12节点的总和。
而i节点的节点条刚好包括了i-lowbit(i)+1~i的数,如lowbit(12)=8,故包括9~12节点。


定义这样的结构给查询前缀和与修改带来无限方便:
设i对应的灰色节点储存总和为C[i]。
查询前缀和:用递归结构查询,由于是顺次相接的结构,查询i节点前缀和时先查询i对应白条,再递归查询剩余区域。
如查询节点7转化为C[7]+C[6]+C[4]

修改节点:此数设计十分巧妙,一个节点的父节点编号即该节点编号+该节点条长度。而修改只需不停更新父节点即可。


以下为代码,注意建树只需执行n次Add即可。

class BIT
{
    public:
        int A[SizeofArr];
        int C[SizeofArr];
        int S;//size
        BIT(int Q,int *Ar)
        {
            S = Q;
            int i;
            for (i=1;i<=S;i++) A[i]=0;
            for (i=1;i<=S;i++) C[i]=0;
            for (i=1;i<=S;i++) Add(i,Ar[i]);
        }
        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<=S)
            {
                C[x] += d;
                x +=lowbit(x);
            }
        }
    private:
        int lowbit(int x)
        {
            return x&-x;
        }

};

例题

1.Ping pong(UVALive4329)

http://acm.hust.edu.cn/vjudge/problem/13895

Unfinished

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值