JAVA SEGMENT TREE LOTS OF EXPLANATIONS, CLASS & RECURSIVE BASED IMPLEMENTATION
Code has comments but feel free to ask anything.\n\nclass NumArray {\n    SegmentTree s;\n    public NumArray(int[] nums) {\n        s = new SegmentTree(nums);\
Code has comments but feel free to ask anything.\n```\nclass NumArray {\n    SegmentTree s;\n    public NumArray(int[] nums) {\n        s = new SegmentTree(nums);\n        s.root = s.build(0, s.arr.length, s.arr);//build returns root Node of what it built\n    }\n    \n    public void update(int index, int val) {\n        int oldvalue = s.arr[index];//Find old value with traditional array, which is O(1) time complexity\n        s.arr[index] = val;//Set our array so that there will be no contradictions if we ever rebuild.\n        //If we are going use build function only once, then we don\'t need to update our traditional array. \n        s.update(s.root, val, index, oldvalue);//Call class\' function\n    }\n    \n    public int sumRange(int left, int right) {\n        return s.rangeSum(s.root, left, right);\n    }\n}\n\nclass Node {\n    int s;//inclusive label\n    int e;//inclusive label\n    int val;\n    Node left;\n    Node right;\n}\n\nclass SegmentTree {\n    Node root;\n    int[] arr;\n\n    SegmentTree(int [] arr) {\n        this.arr = arr;\n    }\n\n    public Node build(int start, int end, int[] arr) {\n        //Start and End integers have nothing to do with building of our SegmentTree, you may ignore them for now\n        //They are needed for querying and updating, so that we can use binary search.\n        Node temp = new Node();\n        if (arr.length == 1) {//which means we are setting a node equal to an element of arr\n            temp.val = arr[0];\n            temp.s = start;\n            temp.e = end-1;//to make it inclusive\n        } else if (arr.length == 0 || start > end || start < 0 || end < 0) {\n            return new Node();// may be better\n        } else {\n            //left = build(start, mid but add 1 if array\'s length is not divisible by 2, left half of the passed array)\n            temp.left = build(start, (start+end)/2 + (arr.length % 2 == 1 ? 1 : 0), Arrays.copyOfRange(arr, 0, arr.length/2 + (arr.length % 2 == 1 ? 1 : 0)));\n            //right = build(start, mid but add 1 if array\'s length is not divisible by 2, right half of the passed array)\n            temp.right = build((start+end)/2 + (arr.length % 2 == 1 ? 1 : 0), end, Arrays.copyOfRange(arr, arr.length/2 + (arr.length % 2 == 1 ? 1 : 0), arr.length));\n            temp.val = temp.left.val + temp.right.val;\n            temp.s = start;\n            temp.e = end-1;//to make it inclusive\n        }\n        return temp;//return this Node to one upper call so that this can be a child of it\'s parent\n    }\n    \n    public int rangeSum(Node node, int l, int r) {\n        if(node == null)\n        {\n            //Range is completely outside given range\n            return 0;\n        }\n        if(l <= node.s && node.e <= r)\n        {\n            //Range is completely inside given range\n            return node.val;\n        }\n        //Range is partially inside and partially outside the given range\n        int mid = (node.s + node.e) / 2;\n        int left = 0;\n        int right = 0;\n        if (l <= mid) {\n            //For example let\'s say root\'s borders are 0:3, l,r=1:2\n            //Then mid will be 1, then we will go into both directions because 1<=1, and 2>=1\n            //Our next calls will be rS(root.left(which is 0:1), 1, 2) and rS(root.right(which is 2:3), 1, 2)\n            //Left call\'s mid will be mid = (0+1)/2 = 0\n            //Then 1<=0 ? No it\'s not, this is why left call\'s variable named left will be 0\n            //Then 2>=0 ? Yes, we will call rS(root.left.right(which is 1:1), 1, 2)\n            //Our left call\'s right call:\n            //1:1 is completely inside 1:2, return the value it holds(equals to arr[1] if our arr is up to date)\n            //Our original call\'s left will be arr[1]\n            //Let\'s calculate our first right function\n            //With same reasoning, our right function will go to left and be root.right.left(which is 2:2)\n            //Our original call\'s right will be arr[2]\n            //Our original/first function will return left + right, which is in fact [1:2] inclusive\n            left = rangeSum(node.left, l, r);\n        } \n        if (r >= mid) {\n            right = rangeSum(node.right, l, r);\n        }\n        return (left + right);\n    }\n    //What we are doing is, going downwards in our tree while we update the values we touch upon\n    //We need to update root always, since it is sum of every element\n    //After that we find mid which is mid value of our current node\'s start and end(inclusive)\n    //At first call this will be (0+arr.length)/2 => mid\n    //If given idx is bigger than mid, then we need to keep searching at right branch\n    //That is why we call the function with root.right as our new root\n    //If given idx is smaller and equals to mid, then we search at left branch\n    //Why did we include equality too? Because I built my tree this way.(where equal things go left)\n    //If idx is between our root\'s borders then we will decrease by the old value, increase by the new value.\n    //If root equals null, we won\'t do anything\n    //We update our traditional array at above.\n    public void update(Node root, int value, int idx, int oldvalue) {\n        if (root == null) {\n            return;\n        }\n        int mid = (root.e + root.s) / 2;\n        if (idx <= root.e && idx >= root.s) {\n            root.val -= oldvalue;\n            root.val += value;\n        } if (idx > mid) {\n            update(root.right, value, idx, oldvalue);\n        } else if (idx <= mid) {\n            update(root.left, value, idx, oldvalue);\n        }\n    }\n}\n```
['Tree', 'Recursion', 'Java']