Data Structures / Range Queries in One Dimension
2.4.14 Cartesian Tree
2-Data-Structures/2.4.14_Cartesian_Tree.cpp
Builds the min Cartesian tree of an array in linear time. A Cartesian tree is a binary tree whose inorder traversal is the original array order and whose heap property is determined by array values. For a min Cartesian tree, each parent has value less than or equal to its children.
Cartesian trees connect arrays, stacks, range minimum queries, treaps, and largest rectangle style problems. Equal values are broken by position, so earlier equal values become ancestors of later equal values.
CartesianTree(a)constructs the tree for arraya.root[]stores the root index.parent[],left[], andright[]store neighboring node indices, or $-1$ if absent.
Implementation
#include <vector>
struct CartesianTree {
int root;
std::vector<int> parent, left, right;
explicit CartesianTree(const std::vector<int> &a)
: root(-1), parent(a.size(), -1), left(a.size(), -1), right(a.size(), -1) {
std::vector<int> st;
for (int i = 0, n = static_cast<int>(a.size()); i < n; i++) {
int last = -1;
while (!st.empty() && a[i] < a[st.back()]) {
last = st.back();
st.pop_back();
}
if (!st.empty()) {
right[st.back()] = i;
parent[i] = st.back();
}
if (last != -1) {
left[i] = last;
parent[last] = i;
}
st.push_back(i);
}
root = st.empty() ? -1 : st[0];
}
};
Example Usage
#include <cassert>
using namespace std;
void inorder(const CartesianTree &t, int u, vector<int> *order) {
if (u == -1) {
return;
}
inorder(t, t.left[u], order);
order->push_back(u);
inorder(t, t.right[u], order);
}
int main() {
vector<int> a{3, 2, 6, 1, 9};
CartesianTree t(a);
assert(t.root == 3);
assert(t.parent[1] == 3);
assert(t.parent[4] == 3);
vector<int> order;
inorder(t, t.root, &order);
for (int i = 0; i < 5; i++) {
assert(order[i] == i);
}
return 0;
}
/*
Builds the min Cartesian tree of an array in linear time. A Cartesian tree is a binary tree whose
inorder traversal is the original array order and whose heap property is determined by array values.
For a min Cartesian tree, each parent has value less than or equal to its children.
Cartesian trees connect arrays, stacks, range minimum queries, treaps, and largest rectangle style
problems. Equal values are broken by position, so earlier equal values become ancestors of later
equal values.
- `CartesianTree(a)` constructs the tree for array `a`.
- `root[]` stores the root index.
- `parent[]`, `left[]`, and `right[]` store neighboring node indices, or $-1$ if absent.
Time Complexity:
- O(n) construction time, where $n$ is the array size.
Space Complexity:
- O(n) for tree arrays and the monotone stack.
*/
#include <vector>
struct CartesianTree {
int root;
std::vector<int> parent, left, right;
explicit CartesianTree(const std::vector<int> &a)
: root(-1), parent(a.size(), -1), left(a.size(), -1), right(a.size(), -1) {
std::vector<int> st;
for (int i = 0, n = static_cast<int>(a.size()); i < n; i++) {
int last = -1;
while (!st.empty() && a[i] < a[st.back()]) {
last = st.back();
st.pop_back();
}
if (!st.empty()) {
right[st.back()] = i;
parent[i] = st.back();
}
if (last != -1) {
left[i] = last;
parent[last] = i;
}
st.push_back(i);
}
root = st.empty() ? -1 : st[0];
}
};
/*** Example Usage ***/
#include <cassert>
using namespace std;
void inorder(const CartesianTree &t, int u, vector<int> *order) {
if (u == -1) {
return;
}
inorder(t, t.left[u], order);
order->push_back(u);
inorder(t, t.right[u], order);
}
int main() {
vector<int> a{3, 2, 6, 1, 9};
CartesianTree t(a);
assert(t.root == 3);
assert(t.parent[1] == 3);
assert(t.parent[4] == 3);
vector<int> order;
inorder(t, t.root, &order);
for (int i = 0; i < 5; i++) {
assert(order[i] == i);
}
return 0;
}