线段树(线段树单点更新之树状数组)--13--线段树--单点更新

给定一个整数数组  nums,求出数组从索引 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。

update(i, val) 函数可以通过将下标为 的数值更新为 val,从而对数列进行修改。

示例:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8
       
 
          

说明:

  1.数组仅可以在 update 函数下进行修改。

  2.你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

分析:

  这是道典型的线段树单点更新的题目,不懂线段树是不行的,线段树知识补充:

  

         线段树的定义:线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

           使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,

           实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。总之,线段树广泛用于求解区间问题。

    线段树编写分为三个步骤:建树,更新,查询。

    话不多说,直接上此题代码吧:

 1 class NumArray {
 2 public:
 3     vector<int> tree;//把数据按树状分支存在数组中,建立一个树状数组
 4     vector<int> num;
 5     int k = 0;//测试用例初始数组遍历变量
 6     int n;//测试用例初始数组数据个数
 7     void pushup(int rt){
 8         tree[rt] = tree[rt<<1] + tree[rt<<1|1];//向上更新父结点值
 9     }
10     void build(int l,int r,int rt){ //建树,rt为当前节点
11         if(l == r){
12             tree[rt] = num[k++];
13             return;
14         }
15         int mid = (l + r) / 2;
16         build(l,mid,rt<<1);//建左子树
17         build(mid + 1,r,rt<<1|1);//建右子树
18         pushup(rt);
19     }
20     NumArray(vector<int>& nums) {
21         n = nums.size();
22         if(n != 0){
23             num = nums;
24             tree = vector<int>(4 * n + 5,0);//注意申请4倍空间!
25             build(1,n,1);//从根节点开始建树
26         }
27     }
28     void UPDATE(int l,int r,int rt,int p,int val){ //更新p节点的值为val
29         if(l == r){
30             tree[rt] = val;
31             return;
32         }
33         int mid = (l + r)  / 2;
34         if(mid >= p)
35             UPDATE(l,mid,rt<<1,p,val);
36         else
37             UPDATE(mid + 1,r,rt<<1|1,p,val);
38         pushup(rt);
39     }
40     void update(int i, int val) {
41         UPDATE(1,n,1,i + 1,val);
42     }
43     int query(int L,int R,int l,int r,int rt){ //查询求 L 到 R 区间和
44         if(L <= l&&r <= R){
45             return tree[rt];
46         }
47         int mid = (l + r) / 2;
48         int sum = 0; 
49         if(mid >= L)
50             sum += query(L,R,l,mid,rt<<1);
51         if(mid < R)
52             sum += query(L,R,mid + 1,r,rt<<1|1);
53         return sum;
54     }
55     int sumRange(int i, int j) {
56         if(n == 0)
57             return 0;
58         return query(i+1,j+1,1,n,1);
59     }
60 };
61 
62 /**
63  * Your NumArray object will be instantiated and called as such:
64  * NumArray* obj = new NumArray(nums);
65  * obj->update(i,val);
66  * int param_2 = obj->sumRange(i,j);
67  */

猜你喜欢

转载自www.cnblogs.com/qinqin-me/p/12299555.html