/**
* 307. Range Sum Query - Mutable
* 1. Time:O(n) Space:O(1)
* 2. Time:O(logn) Space:O(1)
* 3. Time:O(logn) Space:O(1)
*/
// 1. Time:O(n) Space:O(1)
class NumArray {
private int[] nums;
public NumArray(int[] nums) {
this.nums = nums;
}
public void update(int i, int val) {
nums[i] = val;
}
public int sumRange(int i, int j) {
int sum = 0;
for(int cnt=i;cnt<=j;cnt++){
sum += nums[cnt];
}
return sum;
}
}
// 2. Time:O(logn) Space:O(1)
class NumArray {
private int[] tree;
private int n;
public NumArray(int[] nums) {
n = nums.length;
tree = new int[2*n];
buildTree(nums);
}
// Time:O(n) Space:O(n)
private void buildTree(int[] nums){
for(int i=n,j=0;i<2*n;i++,j++){
tree[i] = nums[j];
}
for(int i=n-1;i>0;i--){
tree[i] = tree[2*i] + tree[2*i+1];
}
}
// Time:O(logn) Space:O(1)
public void update(int i, int val) {
i += n;
tree[i] = val;
while(i>0){
int left = i;
int right = i;
if(left%2!=0)
left = i-1;
else
right = i+1;
tree[i/2] = tree[left]+tree[right];
i /= 2;
}
}
// Time:O(logn) Space:O(1)
public int sumRange(int i, int j) {
i += n;
j += n;
int sum = 0;
while(i<=j){
if(i%2==1){
sum += tree[i];
i++;
}
if(j%2==0){
sum += tree[j];
j--;
}
i /= 2;
j /= 2;
}
return sum;
}
}
// 3. Time:O(logn) Space:O(1)
class NumArray {
private Node root;
public NumArray(int[] nums) {
this.root = buildTree(nums,0,nums.length);
}
private Node buildTree(int[] nums, int begin, int end){
if(nums==null || nums.length==0 || begin>=end)
return null;
if(begin == end-1)
return new Node(begin,end,nums[begin]);
Node cur = new Node(begin,end);
int mid = begin+(end-begin)/2;
cur.left = buildTree(nums,begin,mid);
cur.right = buildTree(nums,mid,end);
cur.sum = cur.left.sum + cur.right.sum;
return cur;
}
public void update(int i, int val) {
updateHelper(this.root,i,val);
}
private void updateHelper(Node root, int i, int val){
if(root.begin==root.end-1 && root.begin==i){
root.sum = val;
return;
}
int mid = root.begin+(root.end-root.begin)/2;
if(i<mid)
updateHelper(root.left,i,val);
else
updateHelper(root.right,i,val);
root.sum = root.left.sum + root.right.sum;
}
public int sumRange(int i, int j) {
return sumRangeHelper(this.root,i,j+1);
}
private int sumRangeHelper(Node root,int i,int j){
if(root==null || root.begin>=j || root.end<=i)
return 0;
if(root.begin>=i && root.end<=j)
return root.sum;
int mid = root.begin+(root.end-root.begin)/2;
return sumRangeHelper(root.left,i,Math.min(mid,j))+sumRangeHelper(root.right,Math.max(mid,i),j);
}
private class Node{
private int begin;
private int end;
private int sum;
private Node left;
private Node right;
public Node(int begin,int end,int sum){
this.begin = begin;
this.end = end;
this.sum = sum;
}
public Node(int begin,int end){
this(begin,end,0);
}
}
}