树状数组(弱智线段树)
树状数组中的下标不是正常的索引,而是与二进制相关
如图\(a2\)中存储着\(a1\)中的数据,\(a4\)中存储\(a3和a2\)的数据,依次类推\(a8\)存储\(a4,a6,a7\)的数据。
其中对应的二进制索引\(0001\rightarrow0010\rightarrow0100\)是把二进制中首位\(1\)左移一位也就是\(idx<<=1\)。
对于\(a3,a5,a6,a7\)来说\(0011\rightarrow0010\)就是如果有多个1,那么后面得1就左移一位。比如\(0101\)就是把第一位的\(1\)移动到第二位。\(0011\)就是把第一位的\(1\)移动到第二位相加得到\(0100\),对于\(0111\)来说也是一样的,移动最后一位,变成\(1000\)
怎么实现这个步骤呢?这里有个二进制算法(x & -x)
,比如\((0000 0110) & (1000 0110)\)其中二进制运算时使用的补码。正数的补码是其本身,负数是其反码+1。那么6的补码就是\(0000 0110\),而-6则是\(1111 1010\)。它俩进行与运算得到\(0000 0010\),然源索引值加上这个数就得到了。\(6+2=8\)