题目描述:
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
The update(i, val) function modifies nums by updating the element at index i to val.
Example:
Given nums = [1, 3, 5]
sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8
Note:
1. The array is only modifiable by the update function.
2. You may assume the number of calls to update and sumRange function is distributed evenly.
可以采用树状数组和线段树两种方法解决。
class NumArray {
public:
int lowbit(int x)
{
return x&-x;
}
void add(int i, int x)
{
while(i<v.size())
{
v[i]+=x;
i+=lowbit(i);
}
}
int sum(int n)
{
int sum=0;
while(n>0)
{
sum+=v[n];
n-=lowbit(n);
}
return sum;
}
NumArray(vector<int> nums) {
n=nums;
v=vector<int>(nums.size()+1,0);
for(int i=1;i<v.size();i++) add(i,nums[i-1]);
}
void update(int i, int val) {
add(i+1,val-n[i]);
n[i]=val;
}
int sumRange(int i, int j) {
return sum(j+1)-sum(i);
}
private:
vector<int> v; // 树状数组下标从1开始
vector<int> n; // 原数组下标从0开始
};
class SegmentTreeNode{
public:
int sum;
int begin;
int end;
SegmentTreeNode* left;
SegmentTreeNode* right;
SegmentTreeNode(int b, int e)
{
begin=b;
end=e;
sum=0;
left=NULL;
right=NULL;
}
};
class NumArray {
public:
NumArray(vector<int> nums) {
root=buildTree(nums,0,nums.size()-1);
}
void update(int i, int val) {
update(root,i,val);
}
int sumRange(int i, int j) {
return sumRange(root,i,j);
}
SegmentTreeNode* buildTree(vector<int>& nums, int i, int j) {
if(i>j) return NULL;
SegmentTreeNode* node=new SegmentTreeNode(i,j);
if(i==j) node->sum=nums[i];
else
{
int mid=(i+j)/2;
node->left=buildTree(nums,i,mid); //存在奇数个元素时,中间元素分给左子树
node->right=buildTree(nums,mid+1,j);
node->sum=node->left->sum+node->right->sum; //左右子树构造好之后再给根节点赋值,典型的回溯的过程
}
return node;
}
void update(SegmentTreeNode* node, int i, int val)
{
if(node->begin==i&&node->end==i)
{
node->sum=val;
return;
}
int mid=(node->begin+node->end)/2;
if(i<=mid) update(node->left,i,val); //往左子树走
else update(node->right,i,val); //往右子树走
node->sum=node->left->sum+node->right->sum; //左右子树更新好之后再给根节点赋值,典型的回溯的过程
}
int sumRange(SegmentTreeNode* node, int i, int j) {
if(node->begin==i&&node->end==j) return node->sum;
int mid=(node->begin+node->end)/2;
if(j<=mid) return sumRange(node->left,i,j); //说明[i,j]在左子树范围内
else if(i>mid) return sumRange(node->right,i,j); //说明[i,j]在右子树范围内
else return sumRange(node->left,i,mid)+sumRange(node->right,mid+1,j);
}
private:
SegmentTreeNode* root;
};