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

    落笔记下自己的感悟,本文章主要针对与lowbit函数的讲解,单点修改、单点询问与区间询问(用树状数组解决);

    当遇到区间修改时,树状数组也能搞定,但是毕竟复杂,没有线段树更实在(线段树的延迟更新)。


    lowbit函数


    定义:在二进制状态下,最后一位1与其后面的零所构成的数值。

       例如:    (12)10进制 ------进制转换------  (11002进制

    上例,红色部分(100)即是末尾1与其后面的零构成的数值。其值转成十进制为4;

    所以  lowbit(12) =  4;

    如何用代码实现lowbit函数?

        不难发现,实现方法:     lowbit(n)=n&(~n+1)

        然后又发现   (~n+1) 不就是取反加1嘛,不就是-n的补码?

        然后计算机存储的是补码,所以总结:  lowbit(n)=  (n)&(-n)


    树状数组的实现原理


    给出下图,已经建立好了树状数组。

    树上结点数值的红色部分即lowbit函数值,也是该结点存下的区间长度值。

    例1:

    树结点4,   lowbit(4)=(100)= 4,  区间长度为4,即存下4个数(分别是数组结点1,2,3,4)

    例2:

    树结点6,lowbit(6)=(10)2   =   2,存长度为2的数值,分别是array【5】、array【6】


    规律


    1.建立的树状数组上,每一层的lowbit函数值相等。

    2.lowbit函数值记录的是      区间长度。

    3.树上编号为x的节点, 他的父节点编号为x+lowbit(x)

    4.整棵树的深度为:  (log2n )+ 1

    5.找下一个结点    x-=lowbit(x)


    代码


    当要单点更新时,先更新底层,然后依次更新其父节点,一直到根结点。

    用代码实现则运用上述规律3。

     1 int lowbit(int n){
     2     return n&(-n);
     3 }
     4 
     5 
     6 //在叶节点x  增加 数值k 
     7 void add(int x,int k){
     8     for (;x<=n;x+=lowbit(x)){
     9         root[x]+=k;
    10     }
    11 } 

      

    区间查询运用规律5

     1 int lowbit(int n){
     2     return n&(-n);
     3 }
     4 
     5 // 区间查询 
     6 
     7 int ask(int x){
     8     int ans=0;
     9     for (;x;x-=lowbit(x))
    10         ans+=root[x];
    11     return ans;
    12 } 

    例如上图查询区间【1,7】的和  == root【7】+root【6】+root【4】

    当遇到查询【l,r】区间和时,我们应该知道树状数组大多是用来维护前缀和的,那么只要查询两次区间和  ,然后【1,r】减去【1,l-1】就是答案。

  • 相关阅读:
    Git安装(操作篇)
    Git安装
    ES6基础练习
    SVN的安装与搭建及使用
    解决SVN文件不显示绿色小钩图标问题
    混入(mixin)
    ref属性与props配置项
    docker-compose部署 Mysql 8.0 主从模式基于GTID
    项目统一处理
    Docker Compose实战
  • 原文地址:https://www.cnblogs.com/q1204675546/p/14038858.html
Copyright © 2011-2022 走看看