A Fenwick tree or binary indexed tree is a data structure that can efficiently update elements and calculate prefix sums in a table of numbers.
What is Binary Indexed Tree?
1 2 3 4 5
# PrefixSum defupdate(idx, n): # O(n), update idx-th num in the array defrangeSum(idx1, idx2): # O(1), calculate the sum from idx1-th to idx2-th in the arrayk
从中可以发现,若结点的标号为 n ,则该结点的求和区域长度为 2k ,此处的 k 为 n 的二进制表示的末尾 0 的个数。
1 2
# 只保留n的二进制里最低位的1 2^k = n & (n ^ (n-1)) = n & (-n)
前n项和分别保存在n二进制表示的每个“1”表示
i
二进制
包含A的个数
1
0001
1
2
0010
2
3
0011
3
4
0100
4
5
0101
1
6
0110
2
7
0111
1
8
1000
8
1 2 3 4 5 6 7 8 9 10
# Time : O(nlogn) defbuild(self, nums): n = len(nums) # BIT 数组比原数组多一位! A, C = nums, [0] * (n + 1) for i in range(n): k = i + 1# Start From i+1 while k <= n: C[k] += A[i] k += (k & -k) # Next Parent Node
defupdate(self, i, val): diff, self.A[i] = val - self.A[i], val i += 1# Start From i+1 while i <= self.n: self.C[i] += diff i += (i & -i) # Next Parent Node
defsumRange(self, i, j): res, j = 0, j + 1 while j: # 前j项和(j=j+1了,数组是从0开始index的!) res += self.C[j] j -= (j & -j) # Next Sum Node while i: # 前i-1项和 res -= self.C[i] i -= (i & -i) return res
def__init__(self, nums): self.n = n = len(nums) self.A, self.C = nums, [0] *(n + 1) for i in xrange(n): k = i + 1# tip1 : BIT index from 1 while k <= n: self.C[k] += nums[i] k += k & (-k)
defupdate(self, i, val): diff = val - self.A[i] self.A[i] = val # tip2 : remember to update original array i += 1 while i <= self.n: self.C[i] += diff i += i & (-i)
defsumRange(self, i, j): res = 0 j += 1 while j: res += self.C[j] j -= j & (-j) while i: # tip3 : excluding i, so i do not need to +1 res -= self.C[i] i -= i & (-i) return res
for row in self.preSum: for j in range(1, len(matrix[0])): row[j] += row[j-1]
defupdate(self, row, col, val): diff = val - self.matrix[row][col] self.matrix[row][col] = val
for j in range(col, len(self.matrix[0])): self.preSum[row][j] += diff
defsumRegion(self, row1, col1, row2, col2): s = 0 for i in range(row1, row2+1): row_sum = self.preSum[i][col2] - (self.preSum[i][col1-1] if col1 > 0else0) s += row_sum return s
m, n = len(matrix), len(matrix[0]) self.m, self.n = m, n self.matrix = matrix self.bit = [[0] * (n+1) for _ in xrange(m+1)] for i in xrange(m): for j in xrange(n): self.build(i, j)
defbuild(self, row, col): val = self.matrix[row][col] i = row+1 while i <= self.m: j = col + 1 while j <= self.n: self.bit[i][j] += val j += j & (-j) i += i & (-i)
defupdate(self, row, col, val): diff = val - self.matrix[row][col] self.matrix[row][col] = val i = row+1 while i <= self.m: j = col + 1 while j <= self.n: self.bit[i][j] += diff j += j & (-j) i += i & (-i)
defgetSum(self, row, col): i = row+1 res = 0 while i: j = col + 1 while j: res += self.bit[i][j] j -= j & (-j) i -= i & (-i) return res
idxes = {} for k, v in enumerate(sorted(set(nums))): idxes[v] = k + 1 iNums = [idxes[x] for x in nums] # iNums 相当于重新映射后的Array,其间数值的相对大小没有改变, # 但是值总的范围映射到了[0, n]这样就可以作为BIT的index了!!
def__init__(self, n): self.n = n self.BIT = [0] * (n+1)
defadd(self, i, val): while i <= self.n: self.BIT[i] += val i += i & -i
defsum(self, i): res = 0 while i: res += self.BIT[i] i -= i & -i return res
classSolution(object): defcountSmaller(self, nums): ifnot nums: return [] idxs = {} for k, v in enumerate(sorted(set(nums))): idxs[v] = k + 1 n = len(nums) ftree = FenwickTree(n) res = [] for i in xrange(n-1, -1, -1): res.append(ftree.sum(idxs[nums[i]]-1)) ftree.add(idxs[nums[i]], 1) return res[::-1]