算法详解——线段树

1. 线段树介绍

线段树是一个高度平衡二叉树,它主要用来高效动态地管理一个序列。线段树叶子结点存储序列元素值,分支结点存储一个连续地子区间的某种聚合信息,例如最值、均值等信息。

如图所示:
在这里插入图片描述

用这样一个树状结构来管理序列有什么好处?

  1. 快速地查询某个区间范围,时间复杂度为O(logn)
  2. 快速修改某个元素的值并更新分支结点,时间复杂度为O(logn)
  3. 打上延迟标记之后,可以快速修改某个范围的元素值

线段树的主要操作包括:

  1. 构建线段树
    构建线段树的时间复杂度为 O(n)O(n)O(n),通常是递归构建:
  • 如果区间只有一个元素,那么该节点是叶子节点,直接存储该元素的值。
  • 如果区间有多个元素,则将区间一分为二,递归构建左右子树,节点值为左右子树值的组合。
  1. 区间查询
    查询操作的时间复杂度为 O(log⁡n)O(\log n)O(logn):
  • 如果查询的区间完全覆盖当前节点区间,则直接返回该节点的值。
  • 如果查询的区间与当前节点区间部分重叠,则递归查询左右子树,并将左右子树的结果组合。
  1. 区间更新
    更新操作的时间复杂度同样为 O(log⁡n)O(\log n)O(logn):
  • 如果更新区间完全覆盖当前节点区间,则更新当前节点的值。
  • 如果更新区间与当前节点区间部分重叠,则递归更新左右子树,并将左右子树的结果组合更新当前节点的值。

2. 算法实战

题目如下:

3165. 不包含相邻元素的子序列的最大和

给你一个整数数组 nums 和一个二维数组 queries,其中 queries[i] = [posi, xi]

对于每个查询 i,首先将 nums[posi] 设置为 xi,然后计算查询 i 的答案,该答案为 nums不包含相邻元素的子序列的最大和。

返回所有查询的答案之和。

由于最终答案可能非常大,返回其对 109 + 7 取余 的结果。

子序列 是指从另一个数组中删除一些或不删除元素而不改变剩余元素顺序得到的数组。

分析:如果题目只是单纯的求不包含相邻元素的子序列的最大和,那么该题解法就类似于198.打家劫舍,使用动态规划即可解决。但是题目中给了多次查询,每次查询都会改变序列中一个元素的值,这意味着每次查询都需要从头开始进行计算,显然会超时。

我们可以注意到,如果序列中xi的值被改变,那么其两边子区间的解是不变的,也就是说,我们可以存储许多个子区间的解,当某个元素被修改时只需要更新相应的子区间即可,大大减少计算量。

这样一分析,可以选择使用线段树来保存和维护这些子区间。

使用线段树涉及到如何根据两个子结点的值计算父结点的值,也就是如何合并两个区间的解。如果xi被选择,则xi-1和xi+1都不能被选择,因此合并两个区间时我们需要知道两个区间左右两边的结点是否被选择了。

2.1 定义线段树结点的结构体

首先定义线段树结点的结构体:

struct SegNode
{long long best(){return v11;}void set(long long value){v00 = v01 = v10 = 0;// v11代表的可选可不选,因此如果value为负数就不选v11 = max(value, 0LL);}long long v00, v01, v10, v11;
};

其中v00代表两边结点都不被选择的情况下啊区间的解,而v01则代表左结点不被选择、右结点可选择也可不选择的情况下啊的区间解,v10和v11的含义以此类推。

2.2 定义线段树的主要操作

// 合并两个子区间
void pushup(vector<SegNode> &tree, int x)
{const SegNode &left = tree[2 * x];const SegNode &right = tree[2 * x + 1];tree[x].v00 = max(left.v01 + right.v00, left.v00 + right.v10);tree[x].v10 = max(left.v11 + right.v00, left.v10 + right.v10);tree[x].v01 = max(left.v01 + right.v01, left.v00 + right.v11);tree[x].v11 = max(left.v11 + right.v01, left.v10 + right.v11);
}// 初始化线段树
void segtree_init(vector<SegNode> &tree, vector<int> &nums, int x, int l, int r)
{if (l == r){tree[x].set(nums[l - 1]);return;}int mid = (l + r) / 2;segtree_init(tree, nums, 2 * x, l, mid);segtree_init(tree, nums, 2 * x + 1, mid + 1, r);pushup(tree, x);
}// 更新某个元素
void update(vector<SegNode> &tree, int x, int l, int r, int pos, int value)
{if (l == r){tree[x].set(value);return;}else{int mid = (l + r) / 2;if (pos <= mid)update(tree, 2 * x, l, mid, pos, value);elseupdate(tree, 2 * x + 1, mid + 1, r, pos, value);     pushup(tree, x);}
}

线段树的主要操作还包括查询某个子区间,但是本题只需要全局的解。

2.3 利用线段树解题

class Solution {
public:int maximumSumSubsequence(vector<int>& nums, vector<vector<int>>& queries) {int n = nums.size();// 由于元素个数不一定组成一个满二叉树,所以线段树的结点总数可能超过2 * nvector<SegNode> tree(4 * n + 1);segtree_init(tree, nums, 1, 1, n);constexpr int mod = 1e9 + 7;int ans = 0;for (auto &q : queries){update(tree, 1, 1, n, q[0] + 1, q[1]);ans = (tree[1].best() + ans) % mod;}return ans;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/311.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

XXL-JOB

Github 地址&#xff1a; https://github.com/xuxueli/xxl-job/ 。 官⽅介绍&#xff1a; https://www.xuxueli.com/xxl-job/ 。 XXL-JOB 于 2015 年开源&#xff0c;是⼀款优秀的轻量级分布式任务调度框架&#xff0c;⽀持任务可视化管理、弹性 扩容缩容、任务失败重试和告…

基于 Python 的 Django 框架开发的电影推荐系统

项目简介&#xff1a;本项目是基于 Python 的 Django 框架开发的电影推荐系统&#xff0c;主要功能包括&#xff1a; 电影信息爬取&#xff1a;获取并更新电影数据。数据展示&#xff1a;提供电影数据的列表展示。推荐系统&#xff1a;基于协同过滤算法实现个性化推荐。用户系…

服务器的免密登录和文件传输

在天文学研究中&#xff0c;通常会采用ssh登录服务器&#xff0c;把复杂的计算交给服务器&#xff0c;但是如果你没有进行额外的配置&#xff0c;那么登录服务器&#xff0c;以及和服务器进行文件传输&#xff0c;每次都要输入账号和密码&#xff0c;比较不方便&#xff0c;Win…

interrupt、interrupted、isInterrupted方法详解

interrupt方法的源码&#xff1a; public void interrupt() {if (this ! Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b blocker;if (b ! null) {interrupt0(); //仅仅对当前线程的中断位进行标记b.interrupt();return;}}interrupt0()…

yarn 下载安装、下载依赖、通过 vscode 运行服务(Windows11)

目录 yarn工具前置要求&#xff1a;安装node.js并配置好国内镜像源下载安装下载依赖特别的&#xff1a; 启动服务 yarn 工具 系统&#xff1a;Windows 11 前置要求&#xff1a;安装node.js并配置好国内镜像源 参考&#xff1a;本人写的《node.js下载、安装、设置国内镜像源…

JDK8 Kylin jdk-8u341-linux-x64.tar.gz

JDK8 Kylin jdk-8u341-linux-x64.tar.gz chmod 777 jdk-8u341-linux-x64.tar.gz tar -zxvf jdk-8u341-linux-x64.tar.gz chmod 777 -R jdk1.8.0_341 vi /etc/profile ESC :wq source /etc/profile java -version eclipse JRE tomcat

ssm基于vue框架和elementui组件的手机官网+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 目 录 III 1 绪论 1 1.1 研究背景 1 1.2 目的和意义 1 1.3 论文结构安排 2 2 相关技术 3 2.1 SSM框…

如何封装一个可取消的 HTTP 请求?

前言 你可能会好奇什么样的场景会需要取消 HTTP 请求呢&#xff1f; 确实在实际的项目开发中&#xff0c;可能会很少有这样的需求&#xff0c;但是不代表没有&#xff0c;比如&#xff1a; 假如要实现上述这个公告栏&#xff0c;每点击一个 tab 按钮就会切换展示容器容器中…

关于武汉芯景科技有限公司的马达驱动芯片AT6237开发指南(兼容DRV8837)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 逻辑功能

sqlserver、达梦、mysql调用存储过程(带输入输出参数)

1、sqlserver&#xff0c;可以省略输出参数 --sqlserver调用存储过程&#xff0c;有输入参数&#xff0c;有输出参数--省略输出参数 exec proc_GetReportPrintData 1, , , 1--输出参数为 null exec proc_GetReportPrintData 1, , , 1, null--固定输出参数 exec proc_GetReport…

leetcode 1470.重新排列数组

1.题目要求: 2.题目代码: class Solution { public:vector<int> shuffle(vector<int>& nums, int n) {vector<int> x_array(nums.begin(),nums.begin() n);vector<int> y_array(nums.begin() n,nums.end());int x_index 0;int y_index 0;for…

各地级市能源消耗量数据-基于灯光数据的反演(2000-2022年)

今天带来的数据是的全国各省市能源消耗量数据&#xff0c;省级的能源消耗量数据可以在统计年鉴之中查到&#xff0c;但市级的数据却暂无统计。但今天我们基于一篇论文提供的思路&#xff0c;通过夜间灯光与省级能源消耗量对更小尺度的地区能源消耗量进行反算。原文提供1995-200…

微服务设计模式 - 重试模式(Retry Pattern)

微服务设计模式 - 重试模式&#xff08;Retry Pattern&#xff09; 定义 重试模式&#xff08;Retry Pattern&#xff09;是一种微服务中的设计模式&#xff0c;用于在临时性失败&#xff08;如网络故障或暂时不可用的服务&#xff09;发生时&#xff0c;自动重新尝试请求&…

从源码到成品应用:互联网医院系统与在线问诊APP的开发全解析

今天将全面解析互联网医院系统和在线问诊APP的开发过程&#xff0c;从源码到成品应用&#xff0c;帮助您理解其中的关键技术和实施策略。 一、系统架构设计 互联网医院系统和在线问诊APP的开发首先需要一个合理的系统架构。通常&#xff0c;系统架构分为前端和后端两个部分。…

简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

ZooKeeper 客户端API操作

文章目录 一、节点信息1、创建节点2、获取子节点并监听节点变化3、判断节点是否存在4、客户端向服务端写入数据写入请求直接发给 Leader 节点写入请求直接发给 follow 节点 二、服务器动态上下线监听1、监听过程2、代码 三、分布式锁1、什么是分布式锁?2、Curator 框架实现分布…

C++/list

目录 1.list的介绍 2.list的使用 2.1list的构造 2.2list iterator的使用 2.3list capacity 2.4list element access 2.5list modifers 2.6list的迭代器失效 3.list的模拟实现 4.list与vector的对比 欢迎 1.list的介绍 list的文档介绍 cplusplus.com/reference/list/li…

计算机图形学中向量相关知识chuizhi

一、向量加法 平行四边形法则 两个向量统一起点&#xff0c;构成平行四边形&#xff0c;对角线为向量加和的结果 三角形法则 两个向量尾首相连&#xff0c;从a起点连接到b终点&#xff0c;为向量加法的结果 多向量首尾相连的加法结果为第一个向量的起点到最后一个向量的终点…

私有化视频平台EasyCVR视频汇聚平台接入RTMP协议推流为何无法播放?

私有化视频平台EasyCVR视频汇聚平台兼容性强、支持灵活拓展&#xff0c;平台可提供视频远程监控、录像、存储与回放、视频转码、视频快照、告警、云台控制、语音对讲、平台级联等视频能力。 有用户反馈&#xff0c;项目现场使用RTMP协议接入EasyCVR平台&#xff0c;但是视频却不…

【教程】Git 标准工作流

目录 前言建仓&#xff0c;拉仓&#xff0c;关联仓库修改代码更新本地仓库&#xff0c;并解决冲突提交代码&#xff0c;合入代码其他常用 Git 工作流删除本地仓库和远程仓库中的文件日志打印commit 相关 前言 Git 是日常开发中常用的版本控制工具&#xff0c;配合代码托管仓库…