树状数组求数组的前N项和

树状数组篇:

首先我们来了解一个应用:

我们需要求一个数组的前N项的和:

这么简单的问题我们不是可以这样吗?

for( int i=0;i<N;i++)
{
sum+=array[i];
}
cout<<sum;

但是当我们需要控制时间复杂读小于O(n),则我们需要怎么办呢?

这个时候我们就可以利用树状数组了:

树状数组的修改和控制的时间复杂度都是O(logn)
下面介绍什么是树状数组

C数组就是树状数组 A数组是原数组 C[i]是对应A数组的树状数组 当我们需要的时候就直接按照下表搜索

我们建立一个这样的数组的时间复杂度时O(nlogn)
在这里插入图片描述

由上图可知

C[1]=A[1]

C[2]=A[1]+A[2]

C[3]=A[3]

C[4]=A[1+A[2]+A[3]+A[4]

C[5]=A[5]

C[6]=A[5]+A[6]

C[7]=A[7]

C[8]=A[1]+ A[2]+A[3]+ A[4]+ A[5]+ A[6]+ A[7]+ A[8]


不难发现:
在这里插入图片描述

在这里插入图片描述

SUM(i)就是数组A的前i项的和
比如i=2

假如计算机的位数是16位的则i的二进制是:

0000000000000010

-i的二进制是

1111111111111110

则i&(-i)=2

0000000000000010

1111111111111110

= 0000000000000010=2

具体的去了解计算机的原码、补码、反码的转换方式现在就是上面的具体代码怎么实现:

在Add函数中最重要便是:
在这里插入图片描述

如果A[i]在C中的某些项中则这些项需要加上A[i],因此每一个A[i]中的项都需要进行

一项相同的操作:就是把这个A[i]加到含有它的C数组中间去
所以就有:

#这里使用的是Python语言 如果没有学过就当成伪代码看即可
def Lowbit(x):
	    return x&(-x)
def Add(x,A,C):
	    y=x
	    while x < len(L)-1:
	    A[x] += C[y]
            x+=Lowbit(x)

在C数组做好了那么如何求前N项和呢?
我们要利用这条性质:

在这里插入图片描述

所以就有:



def Get_Sum(x,C)

    sum=0

    while x > 0:

        sum += C[x]

        x -= Lowbit(x)

    return sum

整个完整的代码如下



# This is tree array python source code

import numpy as np 

def Lowbit(x):

    return x&(-x)

def Add(x,P,L):

    y=x

    while x < len(L)-1:

        P[x] += L[y]

        x+=Lowbit(x)

def Build_Tree_Array(L,P):

    for x in range(1,len(L)):

        Add(x,P,L)

def Get_Sum(x,L):

    sum=0

    while x > 0:

        sum += L[x]

        x -= Lowbit(x)

    return sum

if __name__=='__main__':#代码从这里开始执行

    L=np.zeros(11,int)#L是原始的A数组一个一维数组含由11个数 

    P=np.zeros(11,int)#P是C数组初始化都为0
    
    Build_Tree_Array(L,P)

    y=1

    for x in input().split():#这里是输入1 2 3 4 5 6 7 8 9 10这里是给A即L数组赋初值

        L[y]=x

        y+=1

    Build_Tree_Array(L,P)构建数

    print (Get_Sum(4,P))#求前4项的和
#Input:1 2 3 4 5 6 7 8 9 10
# Output:10

上面就是树状数组的内容了 这个数据结构曾经在CCF考试中出现过还是比较重要的 也是ACM的必修课

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值