Blob internal/fenwick/list.go
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
// Package fenwick provides a list data structure supporting prefix sums.
//
// A Fenwick tree, or binary indexed tree, is a space-efficient list
// data structure that can efficiently update elements and calculate
// prefix sums in a list of numbers.
//
// Compared to a common array, a Fenwick tree achieves better balance
// between element update and prefix sum calculation – both operations
// run in O(log n) time – while using the same amount of memory.
// This is achieved by representing the list as an implicit tree,
// where the value of each node is the sum of the numbers in that
// subtree.
//
package fenwick
// List represents a list of numbers with support for efficient
// prefix sum computation. The zero value is an empty list.
type List struct {
// The tree slice stores range sums of an underlying array t.
// To compute the prefix sum t[0] + t[1] + t[k-1], add elements
// which correspond to each 1 bit in the binary expansion of k.
//
// For example, this is how the sum of the 13 first elements
// in t is computed: 13 is 1101₂ in binary, so the elements
// at indices 1101₂ - 1, 1100₂ - 1, and 1000₂ - 1 are added;
// they contain the range sums t[12], t[8] + … t[11], and
// t[0] + … + t[7], respectively.
//
tree []uint32
}
// New creates a new list with the given elements.
func New(n ...uint32) *List {
len := len(n)
t := make([]uint32, len)
copy(t, n)
for i := range t {
if j := i | (i + 1); j < len {
t[j] += t[i]
}
}
return &List{
tree: t,
}
}
// Len returns the number of elements in the list.
func (l *List) Len() int {
return len(l.tree)
}
// Get returns the element at index i.
func (l *List) Get(i int) uint32 {
sum := l.tree[i]
j := i + 1
j -= j & -j
for i > j {
sum -= l.tree[i-1]
i -= i & -i
}
return sum
}
// Set sets the element at index i to n.
func (l *List) Set(i int, n uint32) {
n -= l.Get(i)
for len := len(l.tree); i < len; i |= i + 1 {
l.tree[i] += n
}
}
// Add adds n to the element at index i.
func (l *List) Add(i int, n uint32) {
for len := len(l.tree); i < len; i |= i + 1 {
l.tree[i] += n
}
}
// Sum returns the sum of the elements from index 0 to index i-1.
func (l *List) Sum(i int) uint32 {
var sum uint32
for i > 0 {
sum += l.tree[i-1]
i -= i & -i
}
return sum
}
// SumRange returns the sum of the elements from index i to index j-1.
func (l *List) SumRange(i, j int) uint32 {
var sum uint32
for j > i {
sum += l.tree[j-1]
j -= j & -j
}
for i > j {
sum -= l.tree[i-1]
i -= i & -i
}
return sum
}
// Append appends a new element to the end of the list.
func (l *List) Append(n uint32) {
i := len(l.tree)
l.tree = append(l.tree, 0)
l.tree[i] = n - l.Get(i)
}
|