-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbit.go
414 lines (350 loc) · 9.26 KB
/
bit.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
// Copyright 2019 Geert Van Gorp. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// License which can be found in the LICENSE file.
package bit
import "math/bits"
// Tree represents a Binary Indexed Tree (BIT) type.
type Tree []int32
// New creates a Binary Indexed Tree of n elements.
// If n is not provided, the tree length defaults to zero.
func New(n ...int) Tree {
if len(n) == 0 || n[0] <= 0 {
return Tree{}
}
return make([]int32, n[0])
}
// Len returns the number of elements in the tree.
func Len(t Tree) int {
return len(t)
}
// From creates a Binary Indexed Tree from a slice of numbers.
// When the reUse option is set, the tree will use the numbers
// slice as its backing store, avoiding new allocations. Default
// behavior for the tree is to allocate its own backing store.
func From(numbers []int32, reUse ...bool) Tree {
var t Tree
if len(reUse) == 0 || !reUse[0] {
t = make(Tree, len(numbers))
copy(t, numbers)
} else {
t = numbers
}
for i := range t {
if j := i | (i + 1); 0 <= j && j < len(t) {
t[j] += t[i]
}
}
return t
}
// Reset initializes the length of the tree to zero, but keeps the
// backing store. After Reset, the tree can be re-used with Append.
func (t *Tree) Reset() {
*t = (*t)[:0]
}
// Copy does a deep copy of the src tree. If the dst tree is smaller
// than src, only part of the BIT is copied, up to the length of dst.
// Copy returns the number of elements copied.
func Copy(dst, src Tree) int {
if len(dst) <= len(src) {
return copy(dst, src)
}
n := copy(dst, src)
// compute partial sums for dst[n:]
for i := n; 0 <= i && i < len(dst); i++ {
var num int32
j, k := i, i&(i+1)
for k < j && 0 < j && j < len(dst) {
num += dst[j-1]
j &= j - 1
}
dst[i] = num
}
return len(dst)
}
// Append adds numbers to the back of the tree.
func Append(t Tree, number ...int32) Tree {
if len(number) == 1 {
iNum := len(t)
t = append(t, number[0])
_ = t[iNum]
i, j := iNum, iNum&(iNum+1)
for j < i && 0 < i && i < len(t) {
t[iNum] += t[i-1]
i &= i - 1
}
return t
}
if len(number) > 1 {
l := len(t)
t = append(t, number...)
var imin int
if 0 < l {
imin = 1<<(bits.Len(uint(l))-1) - 1
}
for i := imin; 0 <= i && i < len(t); i++ {
j := i | (i + 1)
if 0 <= j && l <= j && j < len(t) {
t[j] += t[i]
}
}
return t
}
return t
}
// Sum returns the prefix sum at index i of the tree. If i is larger than the
// largest index of the tree, the prefix sum of the largest index is returned.
func (t Tree) Sum(i int) int32 {
if len(t) <= i {
i = len(t) - 1
}
// compute prefix sum at index i by adding relevant partial sums.
var sum int32
for 0 <= i && i < len(t) {
sum += t[i]
i = i&(i+1) - 1
}
return sum
}
// RangeSum returns the prefix sum of the [lo, hi) range. In case of a partial
// overlap of the range with the tree, RangeSum will return the prefix sum
// of the intersection of the given interval with the interval of the tree.
func (t Tree) RangeSum(lo, hi int) int32 {
if hi-lo < 0 {
return 0
}
lo, hi = lo-1, hi-1
lenhi := bits.LeadingZeros64(uint64(hi))
lenlo := bits.LeadingZeros64(uint64(lo))
var sum int32
if lenhi != lenlo {
// compute prefix sum at index hi by adding relevant partial sums
for 0 <= hi && hi < len(t) {
sum += t[hi]
hi = hi&(hi+1) - 1
}
// compute prefix sum at index lo by adding relevant partial sums
for 0 <= lo && lo < len(t) {
sum -= t[lo]
lo = lo&(lo+1) - 1
}
return sum
}
for {
switch {
case lo < hi && 0 <= hi && hi < len(t):
sum += t[hi]
hi = hi&(hi+1) - 1
case hi < lo && 0 <= lo && lo < len(t):
sum -= t[lo]
lo = lo&(lo+1) - 1
default:
return sum
}
}
}
// Sums returns the prefix sums of the tree. If the length of the sums slice
// is too small, Sums fills the slice starting from index 0 and stops when
// the slice is full. Sums returns the number of elements in the sums slice.
func (t Tree) Sums(sums []int32) int {
for i := range sums {
var sum int32
j := i
// calculate sum[i] prefix sum by adding relevant partial sums
for 0 <= j && j < len(t) {
sum += t[j]
j = j&(j+1) - 1
}
sums[i] = sum
}
return len(sums)
}
// Number returns the element at index i.
// If i is outside of the tree, 0 will be returned.
func (t Tree) Number(i int) int32 {
if i < 0 || len(t) <= i {
return 0
}
// calculate number by subtracting relevant partial sums from t[i]
number := t[i]
j := i & (i + 1)
for j < i && 0 < i && i < len(t) {
number -= t[i-1]
i &= i - 1
}
return number
}
// RangeNumbers returns in the buf variable a slice of numbers, as defined
// by the given boundaries. The upper bound is not included. If the lo index
// is out of boundaries, zero will be returned.
func (t Tree) RangeNumbers(lo int, buf []int32) int {
if lo < 0 || lo >= len(t) {
return 0
}
i, j := 0, lo
for i < len(buf) && j < len(t) {
buf[i] = t.Number(j)
i, j = i+1, j+1
}
return i
}
// Numbers returns all numbers in the tree. The caller provides the array
// to store the numbers. If the numbers slice is too short, only numbers
// up to the length of the slice will be returned.
func (t Tree) Numbers(numbers []int32) int {
n := copy(numbers, t)
i := len(t)&^1 - 1
for 0 < i && i < n && i < len(numbers) {
k := i & (i + 1)
for j := i; k < j && 0 < j && j < len(numbers); j &= j - 1 {
numbers[i] -= numbers[j-1]
}
i -= 2
}
return n
}
// Set sets a number at a given index. If the index
// is outside of the tree, no updates are made.
func (t Tree) Set(i int, number int32) {
if i < 0 || len(t) <= i {
return
}
// calculate delta by subtracting relevant partial sums from number
j := i
number -= t[i]
k := i & (i + 1)
for k < i && 0 < i && i < len(t) {
number += t[i-1]
i &= i - 1
}
// add delta to relevant partial sums
for 0 <= j && j < len(t) {
t[j] += number
j |= j + 1
}
}
// Add adds the given vanlue to the number in the tree at index i.
// If the index is outside of the tree boundaries, no value is added.
func (t Tree) Add(i int, value int32) {
// add value to relevant partial sums
for 0 <= i && i < len(t) {
t[i] += value
i |= i + 1
}
}
// Mul multiplies the number at index i with the given value. If the
// index is outside of the tree boundaries, no modifications are done.
func (t Tree) Mul(i int, value int32) int32 {
if i < 0 || len(t) <= i {
return 0
}
// calculate number by subtracting relevant partial sums
j := i
number := t[i]
k := i & (i + 1)
for k < i && 0 < i && i < len(t) {
number -= t[i-1]
i &= i - 1
}
// calculate delta that needs to be added
delta := number * (value - 1)
// add delta to the relevant partial sums
for 0 <= j && j < len(t) {
t[j] += delta
j |= j + 1
}
return number + delta
}
// Shift increases all numbers in the tree with the given value.
func (t Tree) Shift(value int32) {
for i := range t {
t[i] += value << bits.TrailingZeros64(uint64(i)+1)
}
}
// Scale scales all numbers in the tree with the given factor.
func (t Tree) Scale(value int32) {
for i := range t {
t[i] *= value
}
}
// RangeAdd adds a slice of numbers to the numbers in the tree
// at index i and subsequent indices.
func (t Tree) RangeAdd(i int, numbers []int32) {
for j := 0; j < len(numbers) && i < len(t); i, j = i+1, j+1 {
t.Add(i, numbers[j])
}
}
// RangeMul multiplies a slice of numbers with the respective numbers
// in the tree, starting at index i.
func (t Tree) RangeMul(i int, factors []int32) {
for j := 0; j < len(factors) && i < len(t); i, j = i+1, j+1 {
t.Mul(i, factors[j])
}
}
// RangeSet sets a slice of numbers in the tree, starting at index i.
func (t Tree) RangeSet(i int, numbers []int32) {
for j := 0; j < len(numbers) && i < len(t); i, j = i+1, j+1 {
t.Set(i, numbers[j])
}
}
// RangeShift adds the given value to all numbers in the [lo, hi) index
// range of the tree. If lo/hi are outside the boundaries of the tree,
// the [lo, hi) range will be intersected with the tree range.
func (t Tree) RangeShift(lo, hi int, value int32) {
cumVal := value
if lo < 0 {
lo = 0
}
for lo < hi && 0 <= lo && lo < len(t) {
val := value << bits.TrailingZeros64(uint64(lo)+1)
minVal := minabs(cumVal, val)
t[lo] += minVal
if j := lo | (lo + 1); hi <= j {
for 0 <= j && j < len(t) {
t[j] += minVal
j |= j + 1
}
}
cumVal += value
lo++
}
}
func minabs(a, b int32) int32 {
if a <= b {
if 0 <= a {
return a
}
return b
}
if 0 <= b {
return b
}
return a
}
// RangeScale scales all numbers in the [lo, hi) range of the tree with
// the given multiplier. If lo/hi are outside the boundaries of the tree,
// the [lo, hi) range will be intersected with the tree range.
func (t Tree) RangeScale(lo, hi int, multiplier int32) {
for i := lo; i < hi && 0 <= i && i < len(t); i++ {
t.Mul(i, multiplier)
}
}
// SearchSum returns the largest index and corresponding prefix sum that is
// smaller than or equal to the given value. In case the tree is empty, -1 is
// returned.This operation assumes the prefix sums to increase monotonically.
func (t Tree) SearchSum(value int32) (int, int32) {
if len(t) == 0 {
return -1, 0
}
lo, hi := 0, 1<<(bits.Len(uint(len(t)))-1)
toSearch := value
for hi != 0 {
if m := lo + hi; 0 < m && m <= len(t) {
if toSearch >= t[m-1] {
lo += hi
toSearch -= t[m-1]
}
}
hi >>= 1
}
return lo - 1, value - toSearch
}