当前位置: 首页 > article >正文

数据结构——带懒标记的线段树

一、什么是线段树线段树是一种二叉树数据结构用于高效地处理区间查询和区间更新操作。核心思想将数组分成若干个区间线段每个节点代表一个区间通过合并子节点的信息来得到父节点的信息。适用场景区间求和、最大值、最小值区间加、区间乘、区间赋值动态统计数据二、线段树的结构以数组[1, 2, 3, 4, 5]为例[1-5] (15) / \ [1-3] (6) [4-5] (9) / \ / \ [1-2] (3) [3] (3) [4] (4) [5] (5) / \ [1] (1) [2] (2)每个节点存储区间范围该区间的信息如和、最大值等懒标记可选用于区间更新优化例题洛谷P3372题目描述如题已知一个数列 {ai​}你需要进行下面两种操作将某区间每一个数加上 k。求出某区间每一个数的和。输入格式第一行包含两个整数 n,m分别表示该数列数字的个数和操作的总个数。第二行包含 n 个用空格分隔的整数 ai​其中第 i 个数字表示数列第 i 项的初始值。接下来 m 行每行包含 3 或 4 个整数表示一个操作具体如下1 x y k将区间 [x,y] 内每个数加上 k。2 x y输出区间 [x,y] 内每个数的和。输出格式输出包含若干行整数即为所有操作 2 的结果。输入输出样例输入5 5 1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4输出11 8 20说明/提示对于 15% 的数据n≤8m≤10。对于 35% 的数据n≤103m≤104。对于 100% 的数据1≤n,m≤105ai​,k 为正数且任意时刻数列的和不超过 2×1018。题解#includebits/stdc.h using namespace std; using lllong long; //大根树 class SegmentTree { int n; vectorlltree; vectorlllazy; void maintain(int o) { tree[o] tree[o*2]tree[o*21]; } //构建线段树 void build(const vectorlla,int o, int l, int r) { if (lr) { tree[o]a[l]; return; } int m(lr)/2; build(a,o*2,l,m); build(a,o*21,m1,r); maintain(o); } //懒标记下发 void push(int o,int l,int r) { if (lazy[o]!0) { int m (l r) / 2; // 更新左儿子 tree[o*2] lazy[o] * (m - l 1); lazy[o*2] lazy[o]; // 更新右儿子 tree[o*21] lazy[o] * (r - m); lazy[o*21] lazy[o]; lazy[o]0; } } //区域更新 void update(int o,int l,int r,int ql,int qr,ll val) { if (qlr||lqr) { return ; } if (qllrqr) { tree[o] val * (r - l 1); lazy[o] val; return; } int m(lr)/2; push(o, l, r); update(o*2,l,m,ql,qr,val); update(o*21,m1,r,ql,qr,val); maintain(o); } ll query(int o,int l,int r,int ql,int qr) { // if (qlr||lqr) { // return 0; // } if (qllrqr) { return tree[o]; } push(o,l,r); int m(lr)/2; ll l_res 0, r_res 0; if (qlm) { l_resquery(o*2,l,m,ql,qr); } if (qrm) { r_resquery(o*21,m1,r,ql,qr); } return l_resr_res; } public: SegmentTree(const vectorlla) :n(a.size()),tree(4*n),lazy(4*n) { build(a,1,0,n-1); } void update(int l,int r,ll val) { update(1,0,n-1,l,r,val); } ll query(int ql,int qr) { return query(1,0,n-1,ql,qr); } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n,m; cinnm; vectorlla(n); for (int i0;in;i) cina[i]; SegmentTree t(a); while(m--){ int p; cinp; if (p1) { ll x,y,k; cinxyk; t.update(x-1,y-1,k); }else { ll x,y; cinxy; coutt.query(x-1,y-1)\n; } } return 0; }接下来让我们一起分析分析这段代码解释在代码注释里。先简要介绍大体结构#includebits/stdc.h//万能头 using namespace std; using lllong long;//简化代码 //定义了一个线段树的类 class SegmentTree { int n;//树的大小 vectorlltree;//核心数组也是二叉树通过下标的关系来连接 //如 1 是 2 和 3 的根 // 2 是 4 和 5 的根 //也就是 i 是 i*2 和 i*21 的根 vectorlllazy;//懒标记作用是让每一次的更新数组都停留在中间的某个节点 //也就是需要更新的区域的根节点可能不止一个上只有当你要查询的时候碰到了就把标记往下传。 //此处使用两个数组之间是通过下标一一对应当题目复杂懒标记种类多也可以使用结构体 public: }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr);//加速 return 0; }再解释函数部分//维护函数用来维护线段树 void maintain(int o) { tree[o] tree[o*2]tree[o*21]; //此处加法是因为题目是求和可根据题意修改逻辑 }//构建线段树 void build(const vectorlla,int o, int l, int r) { //a数组为题目所给o是当前根节点l和r是当前根节点所包含的a数组区域值在0到n-1; if (lr) {//到叶子节点了 tree[o]a[l]; return; } int m(lr)/2; //如果lr超限可以用 r(l-r)/2;更保险 build(a,o*2,l,m);//建立左子树 build(a,o*21,m1,r);//建立右子树 maintain(o);//递归回去时要不断维护线段树就像从下往上建金字塔一样 }//懒标记下发 void push(int o,int l,int r) { if (lazy[o]!0) {//如果等于0就以为着该节点没有未处理的懒标记 int m (l r) / 2; // 更新左子树 tree[o*2] lazy[o] * (m - l 1); //乘以(m - l 1) 是因为这个节点包含了(m - l 1)个数结合当前逻辑每个数都要增加如果汇聚到根就要乘这么多。 lazy[o*2] lazy[o]; //懒标记继续下传 //可优化的点对于叶子节点的懒标记不可能进行下发基于这一点可以节省空间 // 更新右子树 tree[o*21] lazy[o] * (r - m); lazy[o*21] lazy[o]; lazy[o]0;//消除懒标记 } }//区域更新 void update(int o,int l,int r,int ql,int qr,ll val) { //l和r是当前区域ql和qr是需要更新的区域val是更新值 if (qlr||lqr) { return ; }//如果 当前区域 和 目标区域 没有交集就直接返回 if (qllrqr) {//如果 当前区域 完全在 目标区域 内就进行更新和懒标记添加 tree[o] val * (r - l 1); lazy[o] val; return; } int m(lr)/2; push(o, l, r);//下发懒标记再继续更新 update(o*2,l,m,ql,qr,val); update(o*21,m1,r,ql,qr,val); maintain(o);//维护 }//区域查询 ll query(int o,int l,int r,int ql,int qr) { // if (qlr||lqr) { // return 0; // } //此处的区间交集判断可有可无因为最后面两个if判断已经保证了没有交集的部分不会进行递归 if (qllrqr) { return tree[o]; } push(o,l,r); int m(lr)/2; ll l_res 0, r_res 0; if (qlm) {//如果是 就代表查询区间完全在右子树另一个同理 l_resquery(o*2,l,m,ql,qr); } if (qrm) { r_resquery(o*21,m1,r,ql,qr); } return l_resr_res;//返回区间的和 }public: //构造函数 //初始化列表顺序不可变优点是无额外开销涉及C内部 SegmentTree(const vectorlla) :n(a.size()),tree(4*n10),lazy(4*n10) { build(a,1,0,n-1); } //以下函数重复是为了简化后面使用时的书写。 void update(int l,int r,ll val) { update(1,0,n-1,l,r,val); } ll query(int ql,int qr) { return query(1,0,n-1,ql,qr); }类的部分解释结束。int n,m; cinnm; vectorlla(n); for (int i0;in;i) cina[i]; SegmentTree t(a);//定义一个线段树的类 while(m--){ int p; cinp; if (p1) { ll x,y,k; cinxyk; t.update(x-1,y-1,k);//减一是因为要契合数组下标是从0开始的 }else { ll x,y; cinxy; coutt.query(x-1,y-1)\n; } } return 0;当当当当大功告成不枉我又学了一天的线段树。如果还有不解或写错的地方欢迎在评论区留言小萤还会继续更新算法。

相关文章:

数据结构——带懒标记的线段树

一、什么是线段树?线段树是一种二叉树数据结构,用于高效地处理区间查询和区间更新操作。核心思想:将数组分成若干个区间(线段),每个节点代表一个区间,通过合并子节点的信息来得到父节点的信息。…...

2026年企业AI落地新趋势!RAG知识库实战指南:环境搭建到生产部署全解析

本文介绍了RAG(检索增强生成)技术在企业知识库中的应用,通过从环境搭建到生产部署的完整实战指南,阐述如何利用RAG提升大语言模型回答的准确性、可追溯性和时效性。文章涵盖了基础环境配置、技术选型、数据准备、知识库构建、RAG系…...

终极Mac微信插件:消息防撤回与多开登录完整指南

终极Mac微信插件:消息防撤回与多开登录完整指南 【免费下载链接】WeChatExtension-ForMac A plugin for Mac WeChat 项目地址: https://gitcode.com/gh_mirrors/we/WeChatExtension-ForMac 还在为Mac微信无法防撤回消息而烦恼吗?想要在同一台电脑…...

一文讲清WMS软件是什么?企业为什么要用WMS软件?

在数字化供应链时代,WMS软件(仓储管理系统)已成为企业物流管理的核心。面对仓库混乱、库存不准,很多企业都在问:WMS软件到底是什么?它和Excel或进销存有什么区别?企业为什么要用WMS软件&#xf…...

Java基础小知识

一、 计算机基础知识1.计算机硬件的分类:运算器 控制器 存储器 输入设备 输出设备二、cmd命令窗口的基本用法操着: 说明:盘符名称 : 盘符切换。E:回车,表示切换到E盘dir 查看当前路径下的内容cd 目录 进入单级目录。cd…...

十三张扑克APP

能开发十三张扑克APP的请联系我,有客户渠道需要这类APP,要开发很多款十三张...

P2-CIFAR彩色图片识别

● 🍨 本文为🔗365天深度学习训练营中的学习记录博客 ● 🍖 原作者:K同学啊学习目标:1.编写一个完整的深度学习程序 2. 手动推导卷积层与池化层的计算过程一、前期准备1.设置GPUimport torch import torch.nn as nn im…...

CANN 算子融合技术:Conv-BN-ReLU 与 MatMul-LayerNorm 等融合模式深度解析

CANN 算子融合技术:Conv-BN-ReLU 与 MatMul-LayerNorm 等融合模式深度解析算子融合是提升性能的关键手段。本文深入讲解昇腾支持的算子融合技术、实现原理和应用实践。一、融合技术概述 1.1 为什么要融合 原始: Conv → BN → ReLU → Conv → BN → ReLU融合前内存…...

Gitea库完整从Ubuntu迁移到CentOS中

文章目录 一、概述 二、数据迁移 2.1 获取数据存储路径 2.2 搞事之前先备份(目标服务器CentOS) 2.2.1 停止gitea服务 2.2.2 备份gitea文件夹 2.3 从Ubuntu的数据目录中将数据拷贝到CentOS中 2.4 备份mysql数据库并拷贝到目标服务器(CentOS) 2.4.1 通过mysqldump备份数据库 …...

复杂干扰下考虑异质性的非机动车微观行为建模与仿真【附仿真】

✨ 长期致力于非机动车微观交通行为、异质性、感知—决策—行动三阶段、社会力模型、模糊逻辑研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)非机动车…...

(二) 1. Q-learning的遗憾界分析-高效的Q-learning算法

高效的Q-learning算法 1.1. 无模型算法 1.2. UCB算法 1.3. 文献回顾 无模型(Model-free)强化学习算法(如 Q-learning)无需显式地对环境进行建模,而是直接对价值函数或策略进行参数化和更新。与基于模型(Model-based)的方法相比,这类算法通常更简单、更灵活,因此在现代…...

企业微信外部群如何通过 API 自动化投递结构化小程序卡片

能力介绍 相比于传统的文字链接,结构化的小程序卡片拥有更高的点击率和更规范的视觉展现。该能力允许开发者通过主动调用 API,直接向指定的企业微信外部群投递原生小程序卡片。接口支持自定义动态配置小程序的 appid、首屏页面路径 pagepath&#xff08…...

obsidian博客联动方案

平台文章具有滞后性,最新文章请访问https://blog.nuoyis.net 原先博客需要使用typorapicgotypecho,其中typora编写完毕后需要复制到typecho后台去,极其不方便,然后经过高人指点,我对该软件交互使用开发了新高度 obsidi…...

【考研】2026/5/21

政治2026/5/21唯物辩证法本质上是批判的和革命的:在唯物辩证法看来,一切事物都处在发生、发展和灭亡的过程中,“不存在任何最终的东西、绝对的东西、神圣的东西”。唯物辩证法是客观辩证法与主观辩证法的统一:①客观辩证法&#x…...

1987年4月26日下午15-17点出生性格、运势和命运

1987年4月24日晚上出生的人,如今已步入38岁的门槛。在职业生涯中,这是一个承上启下的关键阶段——既脱离了职场新人的青涩,又尚未到达管理者或专家的巅峰位置。从非命理的角度分析,他们的事业运势与时代变迁、个人选择和社会结构密…...

企业AI合规:数据安全生死线

企业大模型应用中的数据安全合规体系建设 前言:数据安全合规——企业AI落地的必答题 一、合规风险识别与关键挑战 二、技术架构设计与安全合规方案 针对上述四大风险挑战,企业需要从技术架构层面构建纵深防御体系。以下从数据脱敏、访问控制、日志审计、…...

RAG三大冲突与三大死穴及解决方案

RAG :向量召回 稀疏匹配 重排序融合 动态裁剪 —— 冲突根源与工程解法 面向开发者的深度技术解析:揭开 RAG 检索 pipeline 中三个环节的底层冲突,以及幻觉漂移、上下文溢出、检索冗余三大企业级死穴的根治方案。 GitHub 项目地址&#xf…...

《数据挖掘(主编:吕欣 王梦宁)》读书笔记:异常检测方法梳理与实践理解

《数据挖掘(主编:吕欣 王梦宁)》读书笔记:异常检测方法梳理与实践理解本文是学习《数据挖掘(主编:吕欣 王梦宁)》中“异常检测”相关内容后的整理笔记。文章不追求逐条复述教材,而是…...

CANN-ATB多卡推理-昇腾NPU上Llama70B怎么切到8张卡

CANN-ATB多卡推理-昇腾NPU上Llama70B怎么切到8张卡 Llama2-70B 的权重 140GB,单张 Atlas 800I A2 的 64GB 显存放不下。ATB 的多卡推理用 Tensor Parallel 把模型切到多张 NPU 上,每张卡只存 1/N 的权重和 KV Cache。 Tensor Parallel 的切法 Llama2-70B…...

CANN 端侧部署实战:模型转换与服务化

CANN 端侧部署实战:模型转换与服务化如何将训练好的模型快速部署到昇腾端侧设备?本文详解模型格式转换、端侧优化与服务化部署的完整流程。—一、端侧部署概述 1.1 端侧部署的挑战 与数据中心训练不同,端侧部署面临独特的约束:算力…...

写给前端的 CANN-acl:昇腾应用开发接口到底是啥?

写给前端的 CANN-acl:昇腾应用开发接口到底是啥? 之前有兄弟问我:“哥,我想直接调用昇腾的底层API,不用 PyTorch 这些框架,怎么搞?” 好问题。今天一次说清楚。 acl 是啥? acl Asce…...

1987年5月10日晚上23-24点出生性格、运势和命运

出生在下午13-15点这一时段,从心理发展角度来看,最大的性格红利是“社交直觉”。这类人往往在很小的时候就展现出一种能力:能快速识别他人的情绪,并自然地调整自己的行为以促进和谐。这并非玄学,而是因为下午出生婴儿的…...

使用Coze制作一个可以“动”的存钱罐,比记账APP更易用

可视化、AI驱动、自动提醒才是你智能存钱的伙伴──────────────────────────────为什么你的存钱计划总是失败?大多数人的存钱失败,并不是由于缺乏决心,而是缺少反馈。存多少钱、目标达成的比例、离目标还有多远…...

1987年6月14日下午13-15点出生性格、运势和命运

这篇文章讨论终极命题:出生时间只是一个随机数据点,真正的命运由你自己书写。我们将探讨如何利用“1987年5月27日中午11-13点”这个符号,作为自我激励的起点,而非束缚。第一步:解构“出生时间”的神秘性 请明确&#x…...

XRF导向的土壤重金属定量分析方法与应用【附模型】

✨ 长期致力于X射线荧光、土壤重金属、本底扣除、重叠峰解析、光谱联用研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)非对称加权惩罚最小二乘本底扣…...

软件架构分析方法SAAM、ATAM与CBAM

一、SAAM(软件架构分析方法) 1. 核心思路 基于场景,评估架构对可修改性(以及可移植性、可扩充性)的支持程度。 关键是区分 直接场景(现有架构直接支持)和 间接场景(需要修改架构)。 通过分析间接场景的数量与修改代价,定位高风险、高耦合的模块。 2. 典型案例:内…...

SQL出现filesort 一定慢吗

前言:filesort 出现在当无法使用索引排序时,MySQL 必须自己计算排序顺序,这个过程称为 filesort。EXPLAIN 的 Extra 字段会出现 Using filesort。常见触发场景:排序列不在索引中,或顺序/方向与索引不一致ORDER BY 包含…...

Rust技术周刊 2026年第16周

阅读原文: https://mp.weixin.qq.com/s/9en-gxsNB544aG6hgkwJVQ 本周 Rust 生态亮点:GPU 计算突破(KAIO 达 cuBLAS 92.5%、flodl 多 GPU 训练),Tokio 异步优化实战频出,扩展标准库路线图发布,Rust 进入 Pix…...

FinalBurn Neo:一场跨越时空的街机游戏考古之旅

FinalBurn Neo:一场跨越时空的街机游戏考古之旅 【免费下载链接】FBNeo FinalBurn Neo - We are Team FBNeo. 项目地址: https://gitcode.com/gh_mirrors/fb/FBNeo 在数字时代的洪流中,有一群守护者正在用代码为经典街机游戏搭建永生的方舟。Fina…...

大模型的“文字障眼法“:FlipAttack 文本反转越狱技术全解析

一、先打个比方:你听说过"倒着说话"绕过安检吗? 想象一下,有个调皮的小孩想带进游乐园一个违禁品。安检人员耳朵很尖,一听到"炸弹""刀具"这些词就会拦人。于是小孩想了个办法——把话说反。 “我要…...