笛卡尔树通过结合二叉搜索树和堆性质,将RMQ问题转化为LCA问题,利用单调栈在O(n)时间内构建,并配合DFS与稀疏表实现O(1)查询,适用于静态数据的高效区间最值查询。

笛卡尔树(Cartesian Tree)是一种结合了二叉搜索树和堆性质的数据结构,常用于解决RMQ(Range Minimum/Maximum Query,区间最值查询)问题。通过将RMQ转化为LCA(Lowest Common Ancestor,最近公共祖先)问题,笛卡尔树能在线性预处理后实现O(1)查询,是C++中高效处理静态RMQ的重要手段。
笛卡尔树的定义与性质
笛卡尔树满足两个关键性质:
二叉搜索树性质:中序遍历结果等于原数组顺序。最小堆性质:每个节点的值小于等于其子节点的值(最小笛卡尔树)。
构建完成后,原数组任意区间的最小值对应笛卡尔树中该区间对应节点的LCA。这使得RMQ问题可通过LCA求解。
线性时间构建笛卡尔树
利用单调栈可以在O(n)时间内完成构建。核心思路是维护一个值递增的栈,逐个插入元素并调整树结构。
立即学习“C++免费学习笔记(深入)”;
示例代码:
#include #include using namespace std;struct Node {int val, idx;Node left, right;Node(int v, int i) : val(v), idx(i), left(nullptr), right(nullptr) {}};
Node* buildCartesianTree(const vector& arr) {int n = arr.size();if (n == 0) return nullptr;
vector nodes;for (int i = 0; i < n; ++i) nodes.push_back(new Node(arr[i], i));stack stk;for (int i = 0; i val > arr[i]) { lastPop = stk.top(); stk.pop(); } if (!stk.empty()) stk.top()->right = nodes[i]; if (lastPop) nodes[i]->left = lastPop; stk.push(nodes[i]);}Node* root = nullptr;while (!stk.empty()) { root = stk.top(); stk.pop();}return root;
}
该方法确保每个节点最多入栈出栈一次,总时间复杂度为O(n)。
结合RMQ的高效查询方案
构建笛卡尔树后,RMQ(a, b)等价于查找节点a和b在树中的LCA。可通过以下步骤实现高效查询:
对笛卡尔树进行DFS,记录访问节点序列、深度序列和首次出现位置。将LCA问题转化为新的RMQ问题(在深度序列上找最小值)。使用稀疏表(Sparse Table)预处理深度序列,实现O(1)查询。
整体流程:原数组 → 构建笛卡尔树 → DFS生成Euler Tour → ST表预处理 → O(1) RMQ查询。
实际应用场景与注意事项
笛卡尔树适用于静态或半静态数据的RMQ场景,如:
滑动窗口最小值直方图最大矩形面积字符串算法中的某些优化
注意点:
若数组有重复元素,需定义索引优先规则以保证堆性质唯一性。动态更新代价较高,不适合频繁修改的场景。指针操作易出错,可改用数组下标模拟树结构提升稳定性。
基本上就这些,掌握构建和转化思想后,配合ST表就能高效解决多数RMQ问题。
以上就是C++怎么实现一个笛卡尔树_C++数据结构与RMQ问题的高效解法的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1485825.html
微信扫一扫
支付宝扫一扫