树状数组的操作以及运用
小萌新学完树状数组神奇操作以后,初步认识到了数据结构的强大 tqi! 博客记录一下学习,树状数组主要是对数据的离散化处理,把原本n的复杂度降为logn,整体思想跟二分类似,用二进制的形式对数进行类似的处理。
**1.树状数组的离散化处理**(定义)
用d[]数组作为树状数组的存储空间,a[]为要处理的数组,si为数列a[]的前i项和(即前缀和,其实差分数组也是类似的),,树状数组一般用于存储a[]中的前缀和或者差分或者其他性质,将a[]中数据通过二进制进行离散化加快处理速度。举个例子,首先用“7”举例,二进制表示为0111,其中0111=0100+0010+0001;,即7=4+2+1,二进制的每一位代表一块数据的和,所以s7=d[4]+d[2]+d[1];也就是s7=d[0100]+d[0010]+d[0001];也就是将需要求和的数拆分成一个个二进制中'1'的表示(如上中'7'的拆分)。
代码中怎么实现呢?:也就是每次让需要求和的数i 减去他的最后一位的'1' ,减到0结束循环过程如下:以7为例:0111-0001=0110; 0110-0010=0100; 0100-0100=0; 再用一个re存储d[x],最后返回re即可。其中得到最后一位1的数有个函数叫大名鼎鼎的“lowbit”函数;
lowbit函数: return x&(-x);int lowbit(int x) { return x&(-x); }
其中&为逻辑符号”与”操作 ,-x == ~x+1;具体操作可以百度(比我讲得好QAQ)。
使用过程如下 lowbit(7)=0001;(0111 lowbit-> 0001)
这下我们就可以写出树状数组的求和函数啦
int lowbit(int x) { return x&(-x); } int sum(int x) { int re=0; while(x>0) // 直接写x也行一样的 { re+=d[x]; x-=lowbit(x); } return re; }