package LeeCode;
public class LeetCode307 {
private Tree tree;
public LeetCode307(int[] nums) {
tree = new Tree(nums);
}
public void update(int i, int val) {
tree.update(i, val);
}
public int sumRange(int i, int j) {
return tree.sumRange(i, j);
}
public static class Node{
private int left;
private int right;
private int sum;
private Node leftChild;
private Node rightChild;
private Node parent;
public Node(){}
public Node(int left, int right, int sum){
this.left = left;
this.right = right;
this.sum = sum;
parent = null;
}
}
public static class Tree {
private Node root;
private int[] nums;
private int[] sums;
public Tree(int[] nums) {
if(nums == null || nums.length == 0){
return;
}
sums = new int[nums.length];
sums[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sums[i] = sums[i - 1] + nums[i];
}
root = new Node(0, nums.length - 1, sums[nums.length - 1]);
build(root, 0, nums.length - 1);
}
private void build(Node node, int left, int right) {
if (left >= right) {
return;
}
int middle = (left + right) / 2;
Node leftChild = new Node(left, middle, left == 0 ?
sums[middle] : sums[middle] - sums[left - 1]);
leftChild.parent = node;
Node rightChild = new Node(middle + 1, right, sums[right] - sums[middle]);
rightChild.parent = node;
node.leftChild = leftChild;
node.rightChild = rightChild;
build(leftChild, left, middle);
build(rightChild, middle + 1, right);
}
public int sumRange(int left, int right) {
return sumRange(root, left, right);
}
public int sumRange(Node node, int left, int right) {
if (left == node.left && right == node.right) {
return node.sum;
}
int middle = (node.left + node.right) / 2;
if (right <= middle) {
return sumRange(node.leftChild, left, right);
} else {
if (left >= middle + 1) {
return sumRange(node.rightChild, left, right);
} else {
return sumRange(node.leftChild, left, middle) +
sumRange(node.rightChild, middle + 1, right);
}
}
}
public void update(int index, int value) {
Node curNode = root;
while (true) {
if (curNode.left == index && curNode.right == index) {
curNode.sum = value;
break;
}
int middle = (curNode.left + curNode.right) / 2;
if (index <= middle) {
curNode = curNode.leftChild;
} else {
curNode = curNode.rightChild;
}
}
curNode = curNode.parent;
while (curNode != null){
curNode.sum = (curNode.leftChild == null ? 0 : curNode.leftChild.sum) +
(curNode.rightChild == null ? 0 : curNode.rightChild.sum);
curNode = curNode.parent;
}
}
}
public static void main(String[] args) {
int nums[] = {1,3,5};
LeetCode307 leetCode307 = new LeetCode307(nums);
System.out.println(leetCode307.sumRange(0, 2));
leetCode307.update(1,2);
System.out.println(leetCode307.sumRange(0, 2));
}
}