• 树状数组[数据结构]


    树状数组

    ——!x^n+y^n=z^n

      额,图是网上搜来的...

      如图:

    我们令

    c[1]=a[1]

    c[2]=a[2]+c[1]

    c[3]=a[3]

    c[4]=a[4]+c[3]+c[2]

    c[5]=a[5]

    c[6]=c[5]+a[6]

    c[7]=a[7]

    c[8]=a[8]+c[4]+c[6]+c[7]

    c[9]=a[9]

      其实我们是令c[n]的管辖范围为i个元素,而这个i为n化为二进制时从后往前第一个出现1的地方及后面的0组成数的大小(记为lowbit(n))。

      举个例子c[6]=a[5]+a[6]

    6=(110)2,lowbit(6)=(10)2=2;

      但这会产生一个问题,怎么求lowbit?

      利用计算机补码特性我们可以得到:

    lowbit(x)=x&(-x)。[知道补码的同学手推即可,不知道赶紧百度]

      当然作为数据结构要有他的用处。

      利用树状数组我们可以进行两个比较简单的操作:

    <i>求a[1]+a[2]+L+a[x]的值

    <ii>单点更新


    <i>区间查询

    假设我们要求1~x的区间和,我们可以先查询c[x],显然c[x]是包含于我们要求的范围里的;

    但当我们查询完c[x]后,我们应该继续查询未查询到的部分;

    注意到:c[x]的管辖范围:[x-lowbit(x)+1,x],故我们应继续查询c[x-lowbit(x)];

    反复上面操作直至查询完毕。

    代码:

    1 int getsum(x){
    2     int res=0;
    3     for(;x;x-=lowbit(x))
    4         res+=bit[x];
    5     return res;
    6 }

      本人树状数组一直喜欢打成bit啊...

    <ii>单点更新

    我们希望a[x]+inc

    当然我们会先让c[x]+inc;

    然后我们需要找到管辖c[x]的c[y],因为x必须∈[y-lowbit(y)+1,y],我们怎么做这件事?

    其实我们只需要在x后面补上一个0就行了,想想是不是这样。

    代码:

    1 void update(x,inc){
    2     for(;x<=n;x+=lowbit(x))
    3         bit[x]+=inc;
    4 }

      怎么样,是不是觉得代码简短很多?(对比线段树)

  • 相关阅读:
    Log4Net的WinForm使用
    Log4Net的控制台,WinForm,WebApplication使用
    C# 正则表达式判断IP,URL等及其解释
    C++:默认的构造函数
    C++:对象声明
    C++:对象的初始化和构造函数
    C++:类的成员函数定义方式
    C++:类的创建
    C++:this指针
    C++:String类
  • 原文地址:https://www.cnblogs.com/_inx/p/7236204.html
Copyright © 2020-2023  润新知