线段树入门:算法分析

算法分析

线段树采用了分而治之的策略,其点更新、区间更新、区间查询都可以在 时间内完成。树状数组和线段树都用于解决频繁修改和查询的问题,树状数组比线段树更节省空间、代码简单易懂,但是先单数用途更广、更加灵活,凡是可以使用树状数组的问题都可以用线段树来解决。

例题讲解

线段树的题目并不是一成不变的,对于不同的题目,你可能需要修改线段树的模板,来实现各种功能。

区域和检索-数组可修改

给你一个数组 nums ,请你完成两类查询。

  1. 其中一类查询要求 更新 数组 nums 下标对应的值
  2. 另一类查询要求返回数组 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]

示例 1:

输入"NumArray", "sumRange", "update", "sumRange"\[\[1, 3, 5], 0, 2, 1, 2, 0, 2] 输出null, 9, null, 8

解释

NumArray numArray = new NumArray(1, 3, 5);

numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9

numArray.update(1, 2); // nums = 1,2,5

numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8

解题思路

本题是经典的线段树模板题,只需要根据之前的线段树模板稍作修改即可 (将区间最值查询改为区间求和)。

参考代码

复制代码
class NumArray {
public:
struct sgntree{
    int l,r,val;
}T[120010];
vector<int>num;
    void build(int p,int l,int r){
        T[p].l=l,T[p].r=r;
        if(l==r){
            T[p].val=num[l-1];
            return;
        }
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
        T[p].val=T[p<<1].val+T[p<<1|1].val;
    }

    NumArray(vector<int>& nums) {
        num=nums;
        int n=nums.size();
        build(1,1,n);
    }
    void Update(int p,int l,int val){
        if(T[p].l==T[p].r&&T[p].l==l){
            T[p].val=val;
            return;
        }
        int mid=(T[p].l+T[p].r)>>1;
        if(l<=mid)
        Update(p<<1,l,val);
        else
        Update(p<<1|1,l,val);
        T[p].val=T[p<<1].val+T[p<<1|1].val;
    }
    void update(int index, int val) {
        Update(1,index+1,val);
    }
    int query(int p,int l,int r){
        if(T[p].l>=l&&T[p].r<=r){
            return T[p].val;
        }
        int mid=(T[p].l+T[p].r)>>1;
        if(r<=mid)
        return query(p<<1,l,r);
        if(l>mid)
        return query(p<<1|1,l,r);
        return query(p<<1,l,mid)+query(p<<1|1,mid+1,r);
    }
    int sumRange(int left, int right) {
        return query(1,left+1,right+1);
    }
};

/**
 * 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);
 */
相关推荐
luj_176844 分钟前
元设计的诱惑与现实
c语言·开发语言·c++·经验分享·算法
小星星闪亮登场1 小时前
ST表--倍增思想
开发语言·数据结构·c++·算法·思维
马可家的菠萝1 小时前
Vue3 + Canvas 手绘笔记工程化实践:别把画布只当成一张 PNG
前端·vue.js·算法
watersink1 小时前
机器学习极大似然估计与EM算法
人工智能·算法·机器学习
叠层归一研究院1 小时前
如何用程序搭建一个 AGI 种子系统(一):从向量种子到无限生长引擎
人工智能·python·算法·机器学习·agi
科学实验家2 小时前
并 查集
算法
xiaohebang2 小时前
流失预测模型设计:行为特征分析算法选型
大数据·数据结构·经验分享
AI服务老曹2 小时前
视觉算法模型管理性能优化指南:多版本平滑升级、灰度与快速回滚实战
算法·性能优化
l1258652 小时前
# RAG重排序实战:硅基流动bge-reranker-v2-m3在线API vs 本地CrossEncoder,一篇讲透两种方案
数据库·人工智能·python·深度学习·算法·机器学习·langchain
创世宇图3 小时前
【AI量化交易实战】第06讲:小雅再升级——Talib指标库与K线形态量化
算法