-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtree.go
76 lines (62 loc) · 1.75 KB
/
tree.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
package segment
import (
"math"
)
// Tree implementation of segment tree
type Tree struct {
nodes []int //elements of the tree
size int //size number of elements in the original array
}
// NewTree constructs a segment tree and allows to perform RMQ on provided targetArray
func NewTree(from []int) *Tree {
treeSize := calcTreeSize(len(from))
nodes := make([]int, treeSize)
t := &Tree{nodes, len(from)}
t.build(from, 0, 0, len(from)-1)
return t
}
func (t *Tree) build(from []int, node, leftBound, rightBound int) {
if leftBound == rightBound {
t.nodes[node] = from[leftBound]
return
}
bisect := (leftBound + rightBound) / 2
t.build(from, 2*node+1, leftBound, bisect)
t.build(from, 2*node+2, bisect+1, rightBound)
leftMin := t.nodes[2*node+1]
rightMin := t.nodes[2*node+2]
if leftMin < rightMin {
t.nodes[node] = leftMin
} else {
t.nodes[node] = rightMin
}
}
func calcTreeSize(originalSize int) int {
return 1<<uint(math.Ceil(math.Log2(float64(originalSize)))+1) - 1
}
// RangeMinQuery returns minimum element in the [left,right] slice of the original array
func (t *Tree) RangeMinQuery(left, right int) int {
if left > right {
left, right = right, left
}
return (&query{left: left, right: right, nodes: t.nodes}).rangeMinimum(0, 0, t.size-1)
}
type query struct {
left, right int
nodes []int
}
func (q *query) rangeMinimum(node, leftBound, rightBound int) int {
if q.left > rightBound || q.right < leftBound {
return math.MaxInt32
}
if q.left <= leftBound && q.right >= rightBound {
return q.nodes[node]
}
bisect := (leftBound + rightBound) / 2
leftMin := q.rangeMinimum(2*node+1, leftBound, bisect)
rightMin := q.rangeMinimum(2*node+2, bisect+1, rightBound)
if leftMin < rightMin {
return leftMin
}
return rightMin
}