Description
Solution
维护位运算的题目一般都枚举每一个二进制位,来维护每个二进制位的信息。
那么要and y,访问y的每个二进制为1的节点,看看对应的位置有多少个。
但是这一题有一个很棘手的问题:怎么样才能处理加上任意数然后做位运算操作。
我们可以知道一个二进制j的位置上是1,说明2j−1...2j−1这段位置上有值,如果要加上x然后判断这个区间是否有值的话,只用判断[2j−1−x...2j−1−x]这段区间是否有值就好了。
现在问题来了:查询区间[2j−1−x...2j−1−x],如果减成负数了怎么办?
其实如果有一个点值为i,加上了一个x,如果超出了边界2j−1,那么他会到哪里去?其实他相当于进了一位,但是还是会有剩余部分的(就像9+2,满了个10,在个数那里还剩了1个1),那么剩余的部分会从头开始,在0那里加上剩余部分直到无法加为止。
其实只用把左右边界(l,r),l=(l+2j)mod2j,r=(r+2j)mod2j,这样就相当于把左右边界在2j中循环。
那么得出的l,r如果l < r,这一段[l,r]直接树状数组上访问就可以了;如果l>r,那么就分两段[0,r]和[l,2j-1]。
树状数组不能访问0怎么办
本来是[0,2j−1],那么进入树状数组就给他的下标+1就好了。
Code