4
public NumArray(int[] nums) {5
s = new SegmentTree(nums);6
s.root = s.build(0, s.arr.length, s.arr); // build returns root Node of what it built9
public void update(int index, int val) {11
s.arr[index]; // Find old value with traditional array, which is O(1) time complexity12
s.arr[index] = val; // Set our array so that there will be no contradictions if we ever rebuild.13
// If we are going use build function only once, then we don't need to update our traditional15
s.update(s.root, val, index, oldvalue); // Call class' function18
public int sumRange(int left, int right) {19
return s.rangeSum(s.root, left, right);24
int s; // inclusive label25
int e; // inclusive label35
SegmentTree(int[] arr) {39
public Node build(int start, int end, int[] arr) {40
// Start and End integers have nothing to do with building of our SegmentTree, you may ignore42
// They are needed for querying and updating, so that we can use binary search.43
Node temp = new Node();44
if (arr.length == 1) { // which means we are setting a node equal to an element of arr47
temp.e = end - 1; // to make it inclusive48
} else if (arr.length == 0 || start > end || start < 0 || end < 0) {49
return new Node(); // may be better51
// left = build(start, mid but add 1 if array's length is not divisible by 2, left half of the56
(start + end) / 2 + (arr.length % 2 == 1 ? 1 : 0),57
Arrays.copyOfRange(arr, 0, arr.length / 2 + (arr.length % 2 == 1 ? 1 : 0)));58
// right = build(start, mid but add 1 if array's length is not divisible by 2, right half of62
(start + end) / 2 + (arr.length % 2 == 1 ? 1 : 0),64
Arrays.copyOfRange(arr, arr.length / 2 + (arr.length % 2 == 1 ? 1 : 0), arr.length));65
temp.val = temp.left.val + temp.right.val;67
temp.e = end - 1; // to make it inclusive69
return temp; // return this Node to one upper call so that this can be a child of it's parent72
public int rangeSum(Node node, int l, int r) {74
// Range is completely outside given range77
if (l <= node.s && node.e <= r) {78
// Range is completely inside given range81
// Range is partially inside and partially outside the given range82
int mid = (node.s + node.e) / 2;86
// For example let's say root's borders are 0:3, l,r=1:287
// Then mid will be 1, then we will go into both directions because 1<=1, and 2>=188
// Our next calls will be rS(root.left(which is 0:1), 1, 2) and rS(root.right(which is 2:3),90
// Left call's mid will be mid = (0+1)/2 = 091
// Then 1<=0 ? No it's not, this is why left call's variable named left will be 092
// Then 2>=0 ? Yes, we will call rS(root.left.right(which is 1:1), 1, 2)93
// Our left call's right call:94
// 1:1 is completely inside 1:2, return the value it holds(equals to arr[1] if our arr is up96
// Our original call's left will be arr[1]97
// Let's calculate our first right function98
// With same reasoning, our right function will go to left and be root.right.left(which is100
// Our original call's right will be arr[2]101
// Our original/first function will return left + right, which is in fact [1:2] inclusive102
left = rangeSum(node.left, l, r);105
right = rangeSum(node.right, l, r);107
return (left + right);110
// What we are doing is, going downwards in our tree while we update the values we touch upon111
// We need to update root always, since it is sum of every element112
// After that we find mid which is mid value of our current node's start and end(inclusive)113
// At first call this will be (0+arr.length)/2 => mid114
// If given idx is bigger than mid, then we need to keep searching at right branch115
// That is why we call the function with root.right as our new root116
// If given idx is smaller and equals to mid, then we search at left branch117
// Why did we include equality too? Because I built my tree this way.(where equal things go left)118
// If idx is between our root's borders then we will decrease by the old value, increase by the120
// If root equals null, we won't do anything121
// We update our traditional array at above.122
public void update(Node root, int value, int idx, int oldvalue) {126
int mid = (root.e + root.s) / 2;127
if (idx <= root.e && idx >= root.s) {128
root.val -= oldvalue;132
update(root.right, value, idx, oldvalue);133
} else if (idx <= mid) {134
update(root.left, value, idx, oldvalue);