给你一个数组 nums
,请你完成两类查询。
nums
下标对应的值nums
中索引 left
和索引 right
之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray
类:
NumArray(int[] nums)
用整数数组 nums
初始化对象void update(int index, int val)
将 nums[index]
的值 更新 为 val
int sumRange(int left, int right)
返回数组 nums
中索引 left
和索引 right
之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right]
)参考题解:宫水三叶
各类区间和问题:
情况一:数组不变,求区间和
「前缀和」、「树状数组」、「线段树」
情况二:多次修改某个数(单点),求区间和
「树状数组」、「线段树」
情况三:多次修改某个区间,输出最终结果
「差分」
情况四:多次修改某个区间,求区间和
「线段树」、「树状数组」(看修改区间范围大小)
情况五:多次将某个区间变成同一个数,求区间和
「线段树」、「树状数组」(看修改区间范围大小)
线段树代码长而且性能不稳定,所以只有迫不得已的时候才会使用线段树。所以遇到情况四的时候才使用线段树。
本题属于情况二,使用树状数组解决,当做模板直接背过
- class NumArray {
- public:
- vector<int>tree;
- int lowbit(int x){
- return x&-x;
- }
- int query(int x){
- int ans = 0;
- for(int i = x;i > 0;i-=lowbit(i))
- ans += tree[i];
- return ans;
- }
- void add(int x,int u){
- for(int i = x;i<=n;i+=lowbit(i))
- tree[i]+=u;
- }
- vector<int>nums;
- int n;
- NumArray(vector<int>& nums) {
- this->nums = nums;
- n = nums.size();
- tree.resize(n+1,0);
- for(int i = 0;i < n;i++)
- add(i+1, nums[i]);
- }
-
- void update(int index, int val) {
- add(index+1, val - nums[index]);
- nums[index] = val;
- }
-
- int sumRange(int left, int right) {
- return query(right+1)-query(left);
- }
- };
-
- /**
- * 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);
- */