• 线段树(线段树单点更新之树状数组)--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  */
  • 相关阅读:
    mysql 安装
    flying-saucer-pdf使用中字符串过长换行出问题的解决办法
    杂想
    关于MATLAB实验结果求交点问题
    关于学习方向问题
    关于读取文件夹中的图片问题
    关于ROC曲线的碎碎念
    win7(64)+vs2013+opencv3.0配置的辛酸路程
    验证模式和辨识模式
    指纹识别认证
  • 原文地址:https://www.cnblogs.com/qinqin-me/p/12299555.html
Copyright © 2020-2023  润新知