zoukankan      html  css  js  c++  java
  • 树状数组

    树状数组

    简介

    为什么需要树状数组?

    举一个简单的例子,有一个数组[ 9 , 3 , 2 , 5 , 7 ],当我们需要计算数组任意X~X+N项元素的和,若采用传统方式,则需要从X开始一路加到X+N,需要的时间复杂度o(n)。

    若要进一步优化我们可以求出含有对应位置前n项和的数组,例如上述数组对应结果为T[9 , 12 , 14 , 19 , 26],若要再求X~X+N个元素的和,只需计算T[X+N] - T[X]即可,但问题是当在数组某个位置重新插入一个元素时,需要将其位置后面的所有元素都更新,时间复杂度仍是O(N)

    这个时候树状数组就出现了,树状数组的插入和查询任意n项和的时间复杂度都是o(log n)

    以[1 , 2 , 3 , 4 , 5 , 6 , 7 , 8]为节点的一颗完整树状数组如下图

    树状数组每个节点的父节点为pos += lowbit(i),i<n

    • lowbit是指一个整数的二进制表示,从后往前数一直到第一个1所代表的大小

      例如 3 = 011 那么3的lowbit即为1

       6 =0110 那么6的lowbit为 2

    ​ 关于lowbit有一个很简单的求法那就是( X&~X )

    插入或更新元素

    当我们需要插入一个元素时,从这个元素开始,依次更新这个节点一直到树根中所有元素

    以2号节点元素加上5为例,初始化pos = 2

    1.更新2号元素  3+5=8

    2.pos+=lowbit(2) pos = 4 

    3.更新4号元素  10+5=15

    4.pos+=lowbit(4) pos = 8

    5.更新8号元素   36+5=41

    6.8号已到达数组末尾,更新结束 

    查询

    当我们需要查询某位置对应的前n项和,则依次从对应位置开始依次访问直到pos==0

    以节点5前n项和为例,先初始化ans=0,pos = 5

    1.ans+=t[pos] pos = 5 ans = 5

    2.pos -= lowbit(5) pos = 4 ans = 5

    3.ans += t[pos] pos = 4 ans = 15

    4.pos -= lowbit(5) pos = 0 ans = 15

    前5项和为15

  • 相关阅读:
    路由器设置无线网的方法
    numpy, pandas, matplotlib等常用库的学习手册
    文本乱码的解决办法
    漫画:SOA中怎样确定服务的粒度?
    漫画:大公司都在重复造轮子吗?
    演讲稿:新人培养之道
    漫画:全面理解java.lang.IllegalArgumentException及其可用性设计
    漫画:性能、可用性和锁
    漫画:Linux中/etc/resolv.conf文件和puppet工具解析
    《两地书》--Kubernetes(K8s)基础知识(docker容器技术)
  • 原文地址:https://www.cnblogs.com/INnoVationv2/p/10304145.html
Copyright © 2011-2022 走看看