树状数组 & lowbit()
看了很多大佬的博客,每看一篇博客懂一部分,总算是大概理解了树状数组这个神奇又强大的东西;
在这里我做个整合,把我认为好的部分摘录下来;
参考博客1:https://blog.csdn.net/flushhip/article/details/79165701
参考博客2:https://blog.csdn.net/int64ago/article/details/7429868
下面是这两位大佬写的乐章合奏篇~~~~~~~~
首先,我们需要通篇以二进制的视角来学习树状数组,树状数组就是应用二进制的特点来简化不必要的计算过程,利用位运算以实现高效的增删改查;
说到树状数组,顾名思义,这两幅图完全体现了它的核心思想;
树状数组的作用
首先我们搞明白树状数组是用来干嘛的,现在有一个这样的问题:有一个数组a
,下标从0
到n-1
,现在给你w
次修改,q
次查询,修改的话是修改数组中某一个元素的值;查询的话是查询数组中任意一个区间的和;
这个问题很常见,首先分析下朴素做法的时间复杂度,修改是O(1)O(1)的时间复杂度,而查询的话是O(n)O(n)的复杂度,总体时间复杂度为O(qn)O(qn);可能你会想到前缀和来优化这个查询,我们也来分析下,查询的话是O(1)O(1)的复杂度,而修改的时候修改一个点,那么在之后的所有前缀和都要更新,所以修改的时间复杂度是O(n)O(n),总体时间复杂度还是O(qn)O(qn)。
可以发现,两种做法中,要么查询是O(1)O(1),修改是O(n)O(n);要么修改是O(1)O(1),查询是O(n)O(n)。那么就有没有一种做法可以综合一下这两种朴素做法,然后整体时间复杂度可以降一个数量级呢?有的,对,就是树状数组。
树状数组的思想
假设数组a是我们增删改查的对象,但树状数组的思想维护的是 c 数组, 从上面的图我们可以看到,c[i]不是通常意义上的1~i 元素的和;
由图来看看c数组的规则,其中c8 = c4+c6+c7+a8,c6 = c5+a6……先不必纠结怎么做到的,我们只要知道c数组的大致规则即可,很容易知道c8表示a1~a8的和,但是c6却是表示a5~a6的和,为什么会产生这样的区别的呢?或者说发明她的人为什么这样区别对待呢?答案是,这样会使操作更简单!看到这相信有些人就有些感觉了,为什么复杂度被lg了呢?可以看到,c8可以看作a1~a8的左半边和+右半边和,而其中左半边和是确定的c4,右半边其实也是同样的规则把a5~a8一分为二……继续下去都是一分为二直到不能分,可以看看B图。说白了树状数组就是巧妙的利用了二分!
具体如何一分为二的规则通过 lowbit() 函数实现;
lowbit
函数
lowbit
这个函数的功能就是求某一个数的二进制表示中最低的一位1
,举个例子,x = 6
,它的二进制为110
,那么lowbit(x)
就返回2
。
那么怎么求lowbit
呢?
先消掉最后一位
1
,然后再用原数减去消掉最后一位1
后的数,答案就是lowbit(x)
的结果;第二种方法就是计算机组成原理课上老师教过我们求负数的补码的简便方法:把这个数的二进制写出来,然后从右向左找到第一个
1
(这个1
就是我们要求的结果,但是现在表示不出来,后来的操作就是让这个1
能表示出来),这个1
不要动和这个1
右边的二进制不变,左边的二进制依次取反,这样就求出的一个数的补码,说这个方法主要是让我们理解一个负数的补码在二进制上的特征,然后我们把这个负数对应的正数与该负数与运算一下,由于这个1
的左边的二进制与正数的原码对应的部分是相反的,所以相与一定都为0,;由于这个1
和这个1
右边的二进制都是不变的,因此,相与后还是原来的样子,故,这样搞出来的结果就是lowbit(x)
的结果。
两种方法对应的代码依次如下:
int lowbit(x)
{
return x - (x & (x - ));
}
int lowbit(x)
{
return x & -x;
}
树状数组的实现
更新操作:只要更新修改这个点会影响到的c
数组,假设现在修改6(110)
这个点,依据树状数组的性质三,它影响的直系父层就是c[6(110) + lowbit(6(110))] = c[8(1000)]
,但是它肯定不是只影响直系父层,上面所有包含这一层和的层都要更新,但是我们把这个更新传递给直系父层c[8]
,8
这个点的直系父层是c[16]
,依次类推地更新就行了;
查询前缀和:
int sum(int x, ArrayInt c, int n)
{
int ret = ;
for ( ; x > ; ret += c[x], x -= lowbit(x));
return ret;
}
更新操作:
void update(int x, int val, ArrayInt c, int n)
{
for ( ; x <= n; c[x] += val, x += lowbit(x));
}
树状数组 & lowbit()的更多相关文章
- 树状数组lowbit()函数原理的解释 x&(x^(x-1)) x&-x
树状数组lowbit()函数所求的就是最低位1的位置所以可以通过位运算来计算 树状数组通过 x&(x^(x-1)) 能够成功求出lowbit的原因: 首先设x=6,即110(2) 于是我们使 ...
- POJ 2309 BST(树状数组Lowbit)
题意是给你一个满二叉树,给一个数字,求以这个数为根的树中最大值和最小值. 理解树状数组中的lowbit的用法. 说这个之前我先说个叫lowbit的东西,lowbit(k)就是把k的二进制的高位1全部清 ...
- 树状数组Lowbit用法
刚学树状数组,看到这里的时候懵了.经过询问,发现,原来在程序运行时,数据用的都是补码,于是解决了 int Lowbit(x) { return x&(-x); } 如: x =1: 1 &am ...
- (新人的第一篇博客)树状数组中lowbit(i)=i&(-i) 的简单文字证明
第一次写博好激动o(≧v≦)o~~初一狗语无伦次还请多多指教 先了解树状数组http://blog.csdn.net/int64ago/article/details/7429868感觉这个前辈写 ...
- 浅谈树状数组(为什么lowbit(x)=x&(-x)
树状数组是一种支持单点修改和查询前缀和的数据结构 网上很多讲解它的博客了 这里重点讲一下为什么lowbit(x)=x&(-x) 树状数组代码量相对于线段树基本可以不计(太好写了) 因此NOIp ...
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
- bzoj1878--离线+树状数组
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
随机推荐
- 蓝桥 ADV-233 算法提高 队列操作 【STL】
算法提高 队列操作 时间限制:1.0s 内存限制:256.0MB 问题描述 队列操作题.根据输入的操作命令,操作队列(1)入队.(2)出队并输出.(3)计算队中元素个数并输出. ...
- [odb-users] query results not being cached?
Burton, Craig crburton at tnsi.comWed Jun 6 13:58:03 EDT 2012 Previous message: [odb-users] query re ...
- sql时间截取与修改
--修改日,从1号修改到10号UPDATE CHECKINOUT SET CHECKTIME=DATEADD(DAY,9,CHECKTIME) WHERE YEAR(CHECKTIME)=1970 a ...
- sql注入方法以及防范
sql注入方法: 1.数字注入 ; get请求 www.bobo.com?id=1 可以查出 ID等于1的一条数据. 如果有人在链接后面增加 www.bobo.com?id=1 or 1=1 / w ...
- Oracle 助记
title: Oracle 助记 Nothing is impossible! 基础操作 $ sqlplus name/pssword; # 登录数据库 $ create user username ...
- 讯搜问题排查xunsearch
mysql导入数据不成功,开始重建索引后提示 [XSException] ../local/xunsearch/sdk/php/lib/XS.php(1898): DB- 可打印的版本 开始重建索引 ...
- [TJOI2012]桥
Description 有n个岛屿,m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前 ...
- [NOIP2004]火星人
Description 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数 ...
- Joseph UVA 1452 Jump
题目传送门 /* 数学:约瑟夫环问题的变形,首先定义f[i]表示剩下i个人时,最后一个选出的人,有个公式:f[i] = (f[i-1] + m) % i f[1] = 0(编号从0开始),那么类似最后 ...
- 递推DP UVA 1424 Salesmen
题目传送门 /* 题意:给定包含n个点的无向图和一个长度为L的序列,修改尽量少的点使得相邻的数字相同或连通 DP:状态转移方程:dp[i][j] = min (dp[i][j], dp[i-1][k] ...