树状数组(Binary Indexed Tree)

对于学习的线段树方面的,发现很多问题可以用它来求解,但是做题的时候发现,用线段树太容易tle也,很多次也是卡时间过的,然后就发现了树状数组。

首先我们搞明白树状数组是用来干嘛的,树状数组是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值,经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。

所以说,树状数组的求解和线段树的求解有些重合,但是功能没有线段树的那么广泛。但是对树状数组来说,其思想大概是用二进制的方法来实现。

先简单介绍下基本二进制的使用方法:

& 按位与       如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
| 按位或        两个相应的二进制位中只要有一个为1,该位的结果值为1
^ 按位异或    若参加运算的两个二进制位值相同则为0,否则为1
~ 取反           ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0
<< 左移         用来将一个数的各二进制位全部左移N位,右补0  (<<1则是乘2)
>> 右移         将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0(>>1则是除2)

原理:lowbit      

lowbit这个函数的功能就是求某一个数的二进制表示中最低的一位1,举个例子,x = 6,它的二进制为110,那么lowbit(x)就返回2,因为最后一位1表示2

那么怎么求lowbit呢?把这个数的二进制写出来,然后从右向左找到第一个1(这个1就是我们要求的结果,但是现在表示不出来,后来的操作就是让这个1能表示出来),这个1不要动和这个1右边的二进制不变,左边的二进制依次取反,这样就求出的一个数的补码,说这个方法主要是让我们理解一个负数的补码在二进制上的特征,然后我们把这个负数对应的正数与该负数与运算一下,由于这个1的左边的二进制与正数的原码对应的部分是相反的,所以相与一定都为0,;由于这个1和这个1右边的二进制都是不变的,因此,相与后还是原来的样子,故,这样搞出来的结果就是lowbit(x)的结果。

然后后面的看到大佬的博客就直接贴个博客链接了,感觉大佬讲解的很详细了。

贴个大佬的模板:

int lowbit(int x){
    return x & -x;
} 

void update(int i,int val){   //单点更新
    while(i<=n){
        c[i]+=val;
        i+=lowbit(i);   //由叶子节点向上更新树状数组c,从左往右更新
    }
}

int sum(int i){    // 求区间[1,i]内所有元素的和
    int ret=0;
    while(i>0){
        ret+=c[i];  //从右往左累加求和
        i-=lowbit(i);
    }
    return ret;
}

原文博客链接:https://www.cnblogs.com/acgoto/p/8583952.html

原文地址:https://www.cnblogs.com/wushengyang/p/10319111.html

时间: 2024-11-02 05:50:12

树状数组(Binary Indexed Tree)的相关文章

树状树组(Binary Indexed Tree (BIT))的C++部分实现

一.树状数组的用处 树状树组是将一个线性数组保存为“树状”,当修改某点的值.求某个区间的和的时候能够有效的减少时间复杂度.当数组长度为N,实时对数组进行M次修改或求和,最坏的情况下复杂度是O(M*N). 二.树状数组的建立 假设输入数组为 vector<int> nums 将其转化为树状数组的本质在于将数组的原先顺序打乱后,经过特殊的求和方法,组合成新的数组,代码如下.关键点在于k+=k&-k,这是一个利用二进制码的特点完成树状数组下标的选取. 1 size = nums.size()

HDU 3436--Queue-jumpers (树状数组 or Splay Tree)

树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这种方法,很神奇,就是没看懂= = 二分也是可以求的,不过感觉会慢一些…… 思路就是把所有没有询问到的数压缩 例如如果n等于10 值询问到了 2, 7 大概是这样的 [1,2][3,4,5,6,7][8,9,10] 1                2                         

深入理解树状数组

树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询). 百度上给出了令人难以理解的概念,其实这个东西我也是琢磨了一天,参考了大量博客的笔记才搞清楚了大致思路和原理,说说心得吧! 假设数组a[1..n],那么

HDU1166 敌兵布阵(树状数组)

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 60510    Accepted Submission(s): 25649 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

树状数组求逆序数 。,。 蓝桥杯 小朋友排队

先介绍一下树状数组.什么是树状数组呢?树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询).(度娘万岁) 假设A[]数组为存储原来的值得数组,C[]为树状数组. 我们定义:C[i] = A[i - 2^k

士兵杀敌1(树状数组)

首先,要先讲讲树状数组: 树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值. 假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别. 来观察上面的图: 令

树状数组初步

树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可 以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值,且其常数之小是线段树无法做到的. 如图,其中a数组保存了初始读入的n个值,c数组即为我们构建的树状数组. 那么容易发现: C1 = A1 C2 = A1 + A2 C3 = A3 C4 = A1 + A

树状数组 小白篇(1)

身为一名弱省oier中的mengbier,简单讲一下我是怎么学会基础的树状数组的 不算华丽的分割线 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构. 其发明者命名为Fenwick树,最早由Peter M. Fenwick于1994年以<A New Data Structure for Cumulative Frequency Tables>为题发表在 "SOFTWARE PRACTICE A

树状数组详解(图形学算法)

目录 一.从图形学算法说起 1.Median Filter 概述 2.r pixel-Median Filter 算法 3.一维模型 4.数据结构的设计 5.树状数组华丽登场 二.细说树状数组 1.树 or 数组? 2.结点的含义 3.求和操作 4.更新操作 5.lowbit函数O(1)实现 6.小结 三.树状数组的经典模型 1.PUIQ模型 2.IUPQ模型 3.逆序模型 4.二分模型 5.再说Median Filter 6.多维树状数组模型 四.树状数组题集整理 一.从图形学算法说起 1.M

关于树状数组

一. 什么是树状数组? 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询). 个人拙见:其实呢,是一种长的像树的可以高效查询子数组的和以及可以修改元素的数组. 二. 究竟该如何去实现它的功能呢?(以下