307. 区域和检索 - 数组可修改 - 力扣(LeetCode)
看题面单点修改加区间查询 == 一眼线段树 >> 由于没有复杂修改操作 - > 简化为树状数组求解
cpp
int init = []()
{
cin.tie(0) -> sync_with_stdio(false);
return 0;
}();
class NumArray {
public:
NumArray(vector<int>& nums) : sum(nums.size() + 1, 0), num(nums), n(nums.size())
{
for(int i = 0;i < n;i++)
add(i + 1,nums[i]);
}
int lowbit(int x)
{
return x & -x;
}
void add(int pos, int val)
{
for(; pos <= n; pos += lowbit(pos))
sum[pos] += val;
}
void update(int index, int val)
{
add(index + 1, val - num[index]);
num[index] = val;
}
int ask(int x)
{
int ans = 0;
for(; x > 0; x -= lowbit(x))
ans += sum[x];
return ans;
}
int sumRange(int left, int right)
{
return ask(right + 1) - ask(left);
}
private:
vector<int>sum;
vector<int>#
int n;
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* obj->update(index,val);
* int param_2 = obj->sumRange(left,right);
*/
还有一个有意思的解法
cpp
int init = []()
{
cin.tie(0) -> sync_with_stdio(false);
return 0;
}();
class NumArray
{
public:
NumArray(vector<int>& nums)
{
n = nums.size();
v.resize(n << 1);
for(int i = n; i < (n << 1); i++)
v[i] = nums[i - n];
for(int i = n - 1; i > 0; i--)
v[i] = v[i << 1] + v[(i << 1) + 1];
}
void update(int index, int val)
{
int i = n + index;
int diff = val - v[i];
v[i] = val;
while(i > 1)
{
v[i >> 1] += diff;
i >>= 1;
}
}
int sumRange(int left, int right)
{
left += n;right += n;
int sum = 0;
while(left <= right)
{
if(left & 1){ sum += v[left]; left++; }
if(!(right & 1)){ sum += v[right]; right--; }
left >>= 1;right >>= 1;
}
return sum;
}
private:
vector<int> v;
int n;
};