暂存一下线段树模板

template <class Info> // 模板类,Info 是一个模板参数,表示线段树节点存储的信息类型 struct SegmentTree { int n; // 表示线段树中存储的元素个数 vector<Info> info; // 用于存储线段树节点的数组,类型为 Info SegmentTree() : n(0) {} // 默认构造函数,初始化 n 为 0 // 传入 n_ 表示元素个数,v_ 表示初始化的默认值 SegmentTree(int n_, Info v_ = Info()) { init(n_, v_); } // 模板构造函数:传入一个向量,用于初始化线段树 template <class T> SegmentTree(vector<T> init_) { init(init_); } // 初始化函数:传入元素个数和默认值 void init(int n_, Info v_ = Info()) { init(vector(n_, v_)); // 用一个大小为 n_ 的向量初始化,元素值为 v_ } // 模板初始化函数:传入一个向量,用于初始化线段树 template <class T> void init(vector<T> init_) { n = init_.size(); // 记录元素个数 // 初始化 info 数组的大小,4 << __lg(n) 是 2 的 log(n) 次方乘以 4 info.assign(4 << __lg(n), Info()); auto build = [&](auto self, int p, int l, int r) -> void { if (r - l == 1) { // 如果区间长度为 1,说明是叶节点 info[p] = init_[l]; // 将叶节点赋值为初始化向量的对应值 return; } int m = (l + r) / 2; // 计算区间中点 self(self, 2 * p, l, m); // 递归构建左子树 self(self, 2 * p + 1, m, r); // 递归构建右子树 pushup(p); // 更新当前节点的值为其两个子节点的合并值 }; build(build, 1, 0, n); // 调用 Lambda 函数,从根节点开始构建线段树 } void pushup(int p) { info[p] = info[2 * p] + info[2 * p + 1]; } void modify(int p, int l, int r, int x, const Info &v) { if (r - l == 1) { // 如果区间长度为 1,说明是叶节点 info[p] = v; // 直接修改 return; } int m = (l + r) / 2; if (x < m) { modify(2 * p, l, m, x, v); // 递归修改左子树 } else { modify(2 * p + 1, m, r, x, v); // 递归修改右子树 } pushup(p); // 更新当前节点的值为其两个子节点的合并值 } // 对外的修改接口,只需传入修改位置和新值 void modify(int p, const Info &v) { modify(1, 0, n, p, v); // 从根节点开始递归修改 } // 区间查询函数:递归查询区间 [x, y) 的信息 Info rangeQuery(int p, int l, int r, int x, int y) { if (l >= y || r <= x) { // 如果查询区间与当前区间无交集 return Info(); // 返回默认的 Info 对象 } if (l >= x && r <= y) { // 如果当前区间完全包含在查询区间内 return info[p]; // 返回当前节点的值 } int m = (l + r) / 2; // 计算区间中点 // 递归查询左子树和右子树,并合并结果 return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y); } // 对外的区间查询接口,传入区间 [l, r) Info rangeQuery(int l, int r) { return rangeQuery(1, 0, n, l, r); // 从根节点开始查询 } // 查找区间内第一个满足条件的元素 template <class F> int findFirst(int p, int l, int r, int x, int y, F &&pred) { if (l >= y || r <= x) { // 如果查询区间与当前区间无交集 return -1; // 返回 -1 表示未找到 } if (l >= x && r <= y && !pred(info[p])) { // 如果当前区间完全包含在查询区间内且不满足条件 return -1; // 返回 -1 表示未找到 } if (r - l == 1) { // 如果区间长度为 1,说明是叶节点 return l; // 返回叶节点的位置 } int m = (l + r) / 2; // 计算区间中点 int res = findFirst(2 * p, l, m, x, y, pred); // 递归查找左子树 if (res == -1) { // 如果左子树未找到,继续查找右子树 res = findFirst(2 * p + 1, m, r, x, y, pred); } return res; // 返回结果 } // 对外的查找接口,查找区间 [l, r) 内第一个满足条件的元素 template <class F> int findFirst(int l, int r, F &&pred) { return findFirst(1, 0, n, l, r, pred); // 从根节点开始查找 } // 查找区间内最后一个满足条件的元素 template <class F> int findLast(int p, int l, int r, int x, int y, F &&pred) { if (l >= y || r <= x) { // 如果查询区间与当前区间无交集 return -1; // 返回 -1 表示未找到 } if (l >= x && r <= y && !pred(info[p])) { // 如果当前区间完全包含在查询区间内且不满足条件 return -1; // 返回 -1 表示未找到 } if (r - l == 1) { // 如果区间长度为 1,说明是叶节点 return l; // 返回叶节点的位置 } int m = (l + r) / 2; int res = findLast(2 * p + 1, m, r, x, y, pred); // 递归查找右子树 if (res == -1) { // 如果右子树未找到,继续查找左子树 res = findLast(2 * p, l, m, x, y, pred); } return res; // 返回结果 } // 对外的查找接口,查找区间 [l, r) 内最后一个满足条件的元素 template <class F> int findLast(int l, int r, F &&pred) { return findLast(1, 0, n, l, r, pred); // 从根节点开始查找 } };

__EOF__

本文作者爱飞鱼
本文链接https://www.cnblogs.com/mathiter/p/18514820.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   potential-star  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示