@@ -14,50 +14,78 @@ class SegmentTree {
14
14
size
15
15
tree
16
16
constructor ( arr ) {
17
+ // we define tree like this
18
+ // tree[1] : root node of tree
19
+ // tree[i] : i'th node
20
+ // tree[i * 2] : i'th left child
21
+ // tree[i * 2 + 1] : i'th right child
22
+ // and we use bit, shift operation for index
17
23
this . size = arr . length
18
24
this . tree = new Array ( 2 * arr . length )
19
25
this . tree . fill ( 0 )
20
26
21
27
this . build ( arr )
22
28
}
23
29
30
+ // function to build the tree
24
31
build ( arr ) {
25
32
const { size, tree } = this
26
33
// insert leaf nodes in tree
34
+ // leaf nodes will start from index N
35
+ // in this array and will go up to index (2 * N – 1)
27
36
for ( let i = 0 ; i < size ; i ++ ) {
28
37
tree [ size + i ] = arr [ i ]
29
38
}
30
39
31
40
// build the tree by calculating parents
41
+ // tree's root node will contain all leaf node's sum
32
42
for ( let i = size - 1 ; i > 0 ; -- i ) {
33
- tree [ i ] = tree [ i << 1 ] + tree [ ( i << 1 ) | 1 ]
43
+ // current node's value is the sum of left child, right child
44
+ // tree[i] = tree[i * 2] + tree[i * 2 + 1]
45
+ tree [ i ] = tree [ i * 2 ] + tree [ i * 2 + 1 ]
34
46
}
35
47
}
36
48
37
- update ( p , value ) {
49
+ update ( index , value ) {
38
50
const { size, tree } = this
39
51
40
- // set value at position p
41
- tree [ p + size ] = value
42
- p += size
52
+ // only update values in the parents of the given node being changed.
53
+ // to get the parent move to parent node (index / 2)
54
+
55
+ // set value at position index
56
+ index += size
57
+ // tree[index] is leaf node and index's value of array
58
+ tree [ index ] = value
43
59
44
60
// move upward and update parents
45
- for ( let i = p ; i > 1 ; i >>= 1 ) {
61
+ for ( let i = index ; i > 1 ; i >>= 1 ) {
62
+ // i ^ 1 turns (2 * i) to (2 * i + 1)
63
+ // i ^ 1 is second child
46
64
tree [ i >> 1 ] = tree [ i ] + tree [ i ^ 1 ]
47
65
}
48
66
}
49
67
68
+ // interval [L,R) with left index(L) included and right (R) excluded.
50
69
query ( left , right ) {
51
70
const { size, tree } = this
71
+ // cause R is excluded, increase right for convenient
52
72
right ++
53
73
let res = 0
54
74
55
75
// loop to find the sum in the range
56
76
for ( left += size , right += size ; left < right ; left >>= 1 , right >>= 1 ) {
77
+ // L is the left border of an query interval
78
+
79
+ // if L is odd it means that it is the right child of its parent and our interval includes only L and not the parent.
80
+ // So we will simply include this node to sum and move to the parent of its next node by doing L = (L + 1) / 2.
81
+
82
+ // if L is even it is the left child of its parent
83
+ // and the interval includes its parent also unless the right borders interfere.
57
84
if ( ( left & 1 ) > 0 ) {
58
85
res += tree [ left ++ ]
59
86
}
60
87
88
+ // same in R (the right border of an query interval)
61
89
if ( ( right & 1 ) > 0 ) {
62
90
res += tree [ -- right ]
63
91
}
0 commit comments