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

    核心思想:

        (1)树状数组中的每个元素是原数组中一个或者多个连续元素的和。

        (2)在进行连续求和操作a[1]+...+a[n]时,只需要将树状数组中某几个元素的和即可。时间复杂度为O(lgn)

        (3)在进行修改某个元素a[i]时,只需要修改树状数组中某几个元素的和即可。时间复杂度为O(lgn)

      下图就是一个树状数组的示意图:

      解释如下:

      1) a[]: 保存原始数据的数组。(操作(1)求其中连续多个数的和,操作(2)任意修改其中一个元素)

        e[]: 树状数组,其中的任意一个元素e[i]可能是一个或者多个a数组中元素的和。如e[2]=a[1]+a[2]; e[3]=a[3]; e[4]=a[1]+a[2]+a[3]+a[4]。 

      2) e[i]是几个a数组中的元素的和?

        如果数字 i 的二进制表示中末尾有k个连续的0,则e[i]是a数组中2^k个元素的和,则e[i]=a[i-2^k+1]+a[i-2^k+2]+...+a[i-1]+a[i]。

        如:4=100(2)  e[4]=a[1]+a[2]+a[3]+a[4];

          6=110(2)  e[6]=a[5]+a[6]

          7=111(2)  e[7]=a[7]

      3) 后继:可以理解为节点的父亲节点。是离它最近的,且编号末位连续0比它多的就是的父亲,如e[2]是e[1]的后继;e[4]是e[2]的后继。

          如e[4] = e[2]+e[3]+a[4] = a[1]+a[2]+a[3]+a[4] ,e[2]、e[3]的后继就是e[4]。

          后继主要是用来计算e数组,将当前已经计算出的e[i]添加到他们后继中。

        前驱:节点前驱的编号即为比自己小的,最近的,最末连续0比自己多的节点。如e[7]的前驱是e[6],e[6]的前驱是e[4]。

            前驱主要是在计算连续和时,避免重复添加元素。

          如:Sum(7)=a[1]+...+a[7]=e[7]+e[6]+e[4]。(e[7]的前驱是e[6], e[6]的前驱是e[4])

        计算前驱与后继:

          lowbit(i) = ( (i-1) ^ i) & i ;

          节点e[i]的前驱为 e[ i - lowbit(i) ];

          节点e[i]的前驱为 e[ i + lowbit(i) ]

  • 相关阅读:
    Ajax 的 GET 和 POST 模式
    AJax中post与get请求注意事项
    代理模式 (Proxy)
    装饰模式 (Decoratory)
    抽象工厂模式( Abstract Factory )
    单例模式(Singleton)
    原型设计模式
    Intro.js的简介和用法
    mysql 分片
    数据分片(二)如何为数据分片
  • 原文地址:https://www.cnblogs.com/--lr/p/9345776.html
Copyright © 2011-2022 走看看