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

【板子】线段树

单点修改区间和

#include <vector> using namespace std; vector<int> tree, a; // 左右儿子快捷函数 int ls(int now) { return now << 1; } int rs(int now) { return now << 1 | 1; } // 向上更新:子节点更新后更新父节点 void pushup(int now) { tree[now] = tree[ls(now)] + tree[rs(now)]; } // 建树:now当前节点,[l,r]对应原数组区间 void build(int now, int l, int r) { if (l == r) { tree[now] = a[l]; return; } int mid = l + r >> 1; build(ls(now), l, mid); build(rs(now), mid + 1, r); pushup(now); } // 区间查询:查询目标[l,r],当前节点p对应区间[pl,pr] int query(int l, int r, int p, int pl, int pr) { if (l <= pl && pr <= r) return tree[p]; int pm = pl + pr >> 1, ans = 0; if (l <= pm) ans += query(l, r, ls(p), pl, pm); if (pm < r) ans += query(l, r, rs(p), pm + 1, pr); return ans; } // 单点修改:原数组id位置加v void update(int id, int v, int now, int l, int r) { if (l == id && r == id) { tree[now] += v; return; } int mid = l + r >> 1; if (id <= mid) update(id, v, ls(now), l, mid); else update(id, v, rs(now), mid + 1, r); pushup(now); }

区间修改区间和

#include <vector> using namespace std; vector<int> tree, a, tag; int ls(int now) { return now << 1; } int rs(int now) { return now << 1 | 1; } // 给节点p对应区间[pl,pr]统一加d,更新值与懒标记 void addtag(int p, int pl, int pr, int d) { tag[p] += d; tree[p] += d * (pr - pl + 1); } // 向上合并子节点信息 void pushup(int now) { tree[now] = tree[ls(now)] + tree[rs(now)]; } // 下放懒标记:把当前节点标记传给左右儿子,清空自身标记 void pushdown(int p, int pl, int pr) { if (!tag[p]) return; int mid = pl + pr >> 1; addtag(ls(p), pl, mid, tag[p]); addtag(rs(p), mid + 1, pr, tag[p]); tag[p] = 0; } // 建树 void build(int now, int l, int r) { if (l == r) { tree[now] = a[l]; return; } int mid = l + r >> 1; build(ls(now), l, mid); build(rs(now), mid + 1, r); pushup(now); } // 区间查询 int query(int l, int r, int p, int pl, int pr) { if (l <= pl && pr <= r) return tree[p]; pushdown(p, pl, pr); // 访问子节点前必须下放标记 int pm = pl + pr >> 1, ans = 0; if (l <= pm) ans += query(l, r, ls(p), pl, pm); if (pm < r) ans += query(l, r, rs(p), pm + 1, pr); return ans; } // 区间修改:[l,r]全部加d void update(int l, int r, int d, int p, int pl, int pr) { if (l <= pl && pr <= r) { addtag(p, pl, pr, d); return; } pushdown(p, pl, pr); // 分裂区间前下放标记 int pm = pl + pr >> 1; if (l <= pm) update(l, r, d, ls(p), pl, pm); if (pm < r) update(l, r, d, rs(p), pm + 1, pr); pushup(p); }

使用说明

  1. 空间:treetag都要开4 * n
  2. 初始化:
    int n; cin >> n; a.resize(n + 1); tree.resize(4 * n); tag.resize(4 * n, 0); for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n);
  3. 区间[L,R]valupdate(L, R, val, 1, 1, n)
  4. 查询区间[L,R]和:query(L, R, 1, 1, n);//1,1,n用于函数递归,固定传整树
  5. 核心关键点:pushdown必须在递归进入子节点前调用,保证子节点数据是最新的。
http://www.jsqmd.com/news/1145535/

相关文章:

  • 从腾讯混元 Hy3 开源看国产大模型:效率优先时代的产业变局
  • 孤能子视角:蚂蚁灵波的“眼睛”
  • 响应AIGC产教融合新趋势,漫映AI工作流助力高校探索AIGC联合实验室建设
  • Claude Hooks 进阶指南:从原理到实战配置
  • 孩子想学钢琴别急着买琴:先用AutoPiano搭个在线练习台
  • 让读文献效率和质量提升百倍!ChatGPT读文献超级提示词使用全指南
  • 一文读懂脂质体维生素:技术原理、优势与适用人群
  • 计算机毕业设计之家庭财务管理系统
  • 吃灰N1别扔:用OpenList和302重定向搭一个流畅4K影音中心
  • HTTP 超文本传输协议全解:Web 世界的通信规则
  • AI越智能,创作者越累?
  • Swagger 未授权访问自动化检测:Python 脚本实现与 5 个高危路径扫描
  • OpenAI Tokenizer 编码器解析:3种编码方案如何影响中英文Token计数
  • Trae本地AI编程助手:轻量、可控、高响应的单人开发协作者
  • C# 现代语法速成——为 Web API 量身定制
  • Ubuntu 22.04 安装超好用中文输入法rime-ice(雾凇拼音)过程记录
  • 【Java课程设计/毕业设计】基于前后端分离的智能化企业招聘服务平台的设计与实现 基于 SpringBoot 的招聘录用审批管理系统【附源码、数据库、万字文档】
  • 北京一灯大师实地测评立盯三\四\五龙珠Pro透镜
  • 数字图像处理从入门到精通
  • IP 协议全解:互联网的「快递寻址中枢」,搞懂网络层的核心逻辑
  • 【Java课程设计/毕业设计】基于 Web 的线上学习数据分析平台的设计与实现 基于 SpringBoot 的轻量化在线教育学习平台【附源码、数据库、万字文档】
  • 计算机毕业设计之家庭共享权益的健身俱乐部会员管理系统
  • 通俗讲解微服务架构,搞懂互联网大厂主流项目设计思路
  • 企业级私有Docker镜像仓库选型指南:什么才是企业软件交付的优解(2026)
  • 怎么开始投第一条广告
  • 2026成都全域搜索优化服务商全链路解析
  • 科智咨询:2025年中国IDC市场规模达1847.5亿元,AI驱动市场增速显著回升
  • 3分钟掌握阅读APP书源配置:免费解锁全网小说资源的完整指南
  • JDK源码学习笔记:Java码农进阶必备!
  • Codex Goal 的技术原理分析