线段树核心结构体采用数组式存储,tree大小为4*n,根节点编号为1,含n和tree成员;单点修改需递归定位叶子并回溯更新;区间查询须分无交、全含、部分重叠三种情况处理。
线段树在 C++ 中最常用的是数组式(堆式)存储,而非指针式——因为避免动态分配开销、缓存友好、代码简洁。关键点是:tree 数组大小至少为 4 * n(n 是原始数组长度),这是安全上界,能覆盖所有可能节点。
结构体里通常只存区间端点和值,不建议塞太多字段。例如支持「区间求和 + 单点修改」时,tree[i] 存的是对应区间的和:
struct SegmentTree {
vector tree;
int n;
SegmentTree(int size) : n(size), tree(4 * size, 0) {}
void build(const vectorzuojiankuohaophpcnintyoujiankuohaophpcn& arr, int node = 1, int l = 0, int r = -1) {
if (r == -1) r = n - 1;
if (l == r) {
tree[node] = arr[l];
return;
}
int mid = (l + r) / 2;
build(arr, node * 2, l, mid);
build(arr, node * 2 + 1, mid + 1, r);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}};
注意:这里用 node * 2 和 node * 2 + 1 表示左右子节点,根节点编号为 1(不是 0),这是标准
堆式约定;若用 0 作根,则左子为 2*node+1,容易混淆,不推荐初学使用。
单点修改的递归逻辑怎么写才不出错
单点修改本质是「从根往下找唯一包含该位置的叶子,改完再向上更新父节点」。常见错误是边界判断写反、忘记回溯更新、或误把 l == r 当成递归终止但没处理好 mid 计算。
-
update(pos, val, node, l, r) 的 pos 是原始数组下标(0-based),必须严格落在当前 [l, r] 内
- 递归时只进一个分支:若
pos 走左,否则走右
- 更新完子树后,一定要执行
tree[node] = tree[left] + tree[right],漏这步会导致查询结果错误
示例实现:
void update(int pos, long long val, int node = 1, int l = 0, int r = -1) {
if (r == -1) r = n - 1;
if (l == r) {
tree[node] = val;
return;
}
int mid = (l + r) / 2;
if (pos <= mid) {
update(pos, val, node * 2, l, mid);
} else {
update(pos, val, node * 2 + 1, mid + 1, r);
}
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}区间查询为什么不能直接用 (l, r) 套公式
区间查询不是数学公式代入,而是递归拆解覆盖过程。典型错误是认为「只要当前节点区间被查询区间完全包含,就直接返回 tree[node]」,却忽略:若查询区间跨中点,必须拆成两段分别查,再合并结果。
正确逻辑分三种情况:
- 当前区间
[l, r] 与查询区间 [ql, qr] 无交集 → 返回单位元(如求和返回 0)
- 当前区间被完全包含 → 直接返回
tree[node]
- 部分重叠 → 递归查左右子树,返回二者之和
注意:边界比较必须用 ,不是 ;且查询函数应返回值,不是 void:
long long query(int ql, int qr, int node = 1, int l = 0, int r = -1) {
if (r == -1) r = n - 1;
if (qr < l || r < ql) return 0; // 无交集
if (ql <= l && r <= qr) return tree[node]; // 完全包含
int mid = (l + r) / 2;
return query(ql, qr, node * 2, l, mid) +
query(ql, qr, node * 2 + 1, mid + 1, r);
}为什么 build / update / query 都要手动传参而不是封装成类成员方法
初学者常把 l、r 提成类成员变量,结果发现多组查询会互相污染。根本原因是:线段树每个递归调用都依赖当前节点对应的区间范围,这个范围随调用栈深度变化,无法全局固定。
所以必须让 l 和 r 作为参数层层传递。虽然看起来啰嗦,但这是最清晰、最不易出错的方式。C++17 后可用 std::optional 或默认参数简化接口(如上面示例用 r = -1 触发初始化),但底层逻辑不变。
另一个易忽略点:所有操作的时间复杂度都是 O(log n),但常数较大。如果只是做单点改 + 单点查,用普通数组就够了;只有真需要「任意区间求和/最小值/最大值」时,线段树才有意义。
# node
# 栈
# c++
# 为什么
# 封装
# 成员变量
# 结构体
# 递归
# void
# 指针
# 数据结构
# 接口
# 堆
# 单点
# 这是
# 子树
# 的是
# 三种
# 都是
# 太多
# 都要
# 才有
相关文章:
名字制作网站免费,所有小说网站的名字?
建站之星2.7模板快速切换与批量管理功能操作指南
非常酷的网站设计制作软件,酷培ai教育官方网站?
建站之星图片链接生成指南:自助建站与智能设计教程
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
c# 在ASP.NET Core中管理和取消后台任务
常州自助建站费用包含哪些项目?
Android使用GridView实现日历的简单功能
实现虚拟支付需哪些建站技术支撑?
专业网站设计制作公司,如何制作一个企业网站,建设网站的基本步骤有哪些?
建站之星上传入口如何快速找到?
山东网站制作公司有哪些,山东大源集团官网?
Swift中switch语句区间和元组模式匹配
整蛊网站制作软件,手机不停的收到各种网站的验证码短信,是手机病毒还是人为恶搞?有这种手机病毒吗?
手机网站制作与建设方案,手机网站如何建设?
,石家庄四十八中学官网?
建站之星代理如何优化在线客服效率?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
建站DNS解析失败?如何正确配置域名服务器?
小型网站制作HTML,*游戏网站怎么搭建?
如何用搬瓦工VPS快速搭建个人网站?
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
ui设计制作网站有哪些,手机UI设计网址吗?
如何通过PHP快速构建高效问答网站功能?
如何通过商城免费建站系统源码自定义网站主题?
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?
网站制作大概多少钱一个,做一个平台网站大概多少钱?
实例解析angularjs的filter过滤器
建站之星Pro快速搭建教程:模板选择与功能配置指南
独立制作一个网站多少钱,建立网站需要花多少钱?
教学论文网站制作软件有哪些,写论文用什么软件
?
宁波自助建站系统如何快速打造专业企业网站?
平台云上自助建站如何快速打造专业网站?
Bpmn 2.0的XML文件怎么画流程图
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
css网站制作参考文献有哪些,易聊怎么注册?
如何确认建站备案号应放置的具体位置?
建站之星北京办公室:智能建站系统与小程序生成方案解析
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
深入理解Android中的xmlns:tools属性
学校免费自助建站系统:智能生成+拖拽设计+多端适配
高防服务器如何保障网站安全无虞?
香港服务器如何优化才能显著提升网站加载速度?
如何获取上海专业网站定制建站电话?
网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?
建站主机是否属于云主机类型?
外贸公司网站制作哪家好,maersk船公司官网?
赚钱网站制作软件,建一个网站怎样才能赚钱?是如何盈利的?
*请认真填写需求信息,我们会在24小时内与您取得联系。