Given an integer array in the construct method, implement two methods query(start, end)
and modify(index, value)
:
- For query(start, end), return the sum from index start to index end in the given array.
- For modify(index, value), modify the number in the given index to value
Example
Example 1
Input:
[1,2,7,8,5]
[query(0,2),modify(0,4),query(0,1),modify(2,1),query(2,4)]
Output: [10,6,14]
Explanation:
Given array A = [1,2,7,8,5].
After query(0, 2), 1 + 2 + 7 = 10,
After modify(0, 4), change A[0] from 1 to 4, A = [4,2,7,8,5].
After query(0, 1), 4 + 2 = 6.
After modify(2, 1), change A[2] from 7 to 1,A = [4,2,1,8,5].
After query(2, 4), 1 + 8 + 5 = 14.
Example 2
Input:
[1,2,3,4,5]
[query(0,0),query(1,2),quert(3,4)]
Output: [1,5,9]
Explantion:
1 = 1
2 + 3 = 5
4 + 5 = 9
Challenge
O(logN) time for query
and modify
.
Notice
We suggest you finish problem Segment Tree Build, Segment Tree Query and Segment Tree Modify first.
思路:这题典型的segment tree或者树状数组的解法;只有这样才能做到 O(logN)的query和modify操作;
public class Solution {
/* you may need to use some attributes here */
/*
* @param A: An integer array
*/
private SegmentTree tree;
public Solution(int[] A) {
tree = new SegmentTree(A);
}
/*
* @param start: An integer
* @param end: An integer
* @return: The sum from start to end
*/
public long query(int start, int end) {
return tree.querySum(start, end);
}
/*
* @param index: An integer
* @param value: An integer
* @return: nothing
*/
public void modify(int index, int value) {
tree.modify(index, value);
}
private class SegmentTreeNode {
public int start, end;
public long sum;
public SegmentTreeNode left, right;
public SegmentTreeNode(int start, int end) {
this.start = start;
this.end = end;
this.sum = 0;
this.left = null;
this.right = null;
}
}
private class SegmentTree {
private SegmentTreeNode root;
private int size;
public SegmentTree(int[] A) {
this.size = A.length;
this.root = buildTree(A, 0, size - 1);
}
private SegmentTreeNode buildTree(int[] A, int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode node = new SegmentTreeNode(start, end);
if(start == end) {
node.sum = A[start];
return node;
}
int mid = start + (end - start) / 2;
node.left = buildTree(A, start, mid);
node.right = buildTree(A, mid + 1, end);
node.sum = node.left.sum + node.right.sum;
return node;
}
private long querySum(SegmentTreeNode root, int start, int end) {
if(root.start == start && root.end == end) {
return root.sum;
}
int mid = root.start + (root.end - root.start) / 2;
long leftsum = 0, rightsum = 0;
if(start <= mid) {
leftsum = querySum(root.left, start, Math.min(mid, end));
}
if(end >= mid + 1) {
rightsum = querySum(root.right, Math.max(start, mid + 1), end);
}
return leftsum + rightsum;
}
private void modify(SegmentTreeNode root, int index, int value) {
if(root.start == root.end && root.end == index) {
root.sum = value;
return;
}
int mid = root.start + (root.end - root.start) / 2;
if(index <= mid) {
modify(root.left, index, value);
} else {
modify(root.right, index, value);
}
root.sum = root.left.sum + root.right.sum;
}
public long querySum(int start, int end) {
return querySum(root, start, end);
}
public void modify(int index, int value) {
modify(root, index, value);
}
}
}