68# ifndef TPL_CARTESIAN_TREE_H
69# define TPL_CARTESIAN_TREE_H
74# include <initializer_list>
75# include <type_traits>
117 template <
typename T,
class Comp>
123 static constexpr size_t NONE =
static_cast<size_t>(-1);
148 for (
size_t i = 0; i <
n_; ++i)
185 for (
size_t i = 0; i <
n_; ++i)
216 for (
size_t i = 0; i <
n_; ++i)
230 for (
auto it =
il.begin(); it !=
il.end(); ++it)
244 for (
auto it =
values.get_it(); it.has_curr(); it.next_ne())
245 data_(i++) = it.get_curr();
257 for (
size_t i = 0; i <
n_; ++i)
287 <<
"Gen_Cartesian_Tree::left_child: i=" << i <<
" >= n=" <<
n_;
297 <<
"Gen_Cartesian_Tree::right_child: i=" << i <<
" >= n=" <<
n_;
307 <<
"Gen_Cartesian_Tree::parent_of: i=" << i <<
" >= n=" <<
n_;
317 <<
"Gen_Cartesian_Tree::data_at: i=" << i <<
" >= n=" <<
n_;
333 <<
"Gen_Cartesian_Tree::is_leaf: i=" << i <<
" >= n=" <<
n_;
341 <<
"Gen_Cartesian_Tree::is_root: i=" << i <<
" >= n=" <<
n_;
360 size_t max_depth = 0;
374 auto [node, depth] =
stk(--top);
375 if (depth > max_depth)
380 stk(top++) = {
left_(node), depth + 1};
412 while (curr !=
NONE or top > 0)
420 result(idx++) = curr;
442 for (
size_t i = 0; i <
n_; ++i)
454 noexcept(std::swap(
n_,
other.n_)) &&
455 std::is_nothrow_swappable_v<Comp>)
471 template <std::totally_ordered T>
483 template <std::totally_ordered T>
519 template <
typename T,
class Comp>
536 return a.
depth <= b.depth ? a : b;
551 const size_t n =
tree_.size();
563 for (
size_t i = 0; i < n; ++i)
580 auto make_frame = [
this](
const size_t node,
const size_t depth) ->
Frame
582 return {node, 0, depth,
tree_.left_child(node),
tree_.right_child(node)};
602 if (
frame.left != NONE)
605 else if (
frame.phase == 1)
608 if (
frame.left != NONE)
617 if (
frame.right != NONE)
623 if (
frame.right != NONE)
703 size_t lca(
const size_t u,
const size_t v)
const
705 const size_t n =
tree_.size();
707 <<
"Gen_Euler_Tour_LCA::lca: u=" << u <<
" >= n=" << n;
709 <<
"Gen_Euler_Tour_LCA::lca: v=" << v <<
" >= n=" << n;
725 <<
"Gen_Euler_Tour_LCA::depth_of: u=" << u <<
" >= n=" <<
tree_.size();
733 size_t distance(
const size_t u,
const size_t v)
const
748 return tree_.is_empty();
777 template <std::totally_ordered T>
789 template <std::totally_ordered T>
827 template <
typename T,
class Comp>
870 <<
"Gen_Cartesian_Tree_RMQ::query: l=" <<
l <<
" > r=" <<
r;
872 <<
"Gen_Cartesian_Tree_RMQ::query: r=" <<
r <<
" >= n=" <<
lca_.
size();
889 <<
"Gen_Cartesian_Tree_RMQ::query_idx: l=" <<
l <<
" > r=" <<
r;
891 <<
"Gen_Cartesian_Tree_RMQ::query_idx: r=" <<
r <<
" >= n=" <<
lca_.
size();
904 return lca_.tree().data_at(i);
916 return lca_.is_empty();
922 return lca_.tree().values();
936 template <std::totally_ordered T>
948 template <std::totally_ordered T>
C++20 concepts for constraining comparison functors.
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Standard functor implementations and comparison objects.
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
void swap(Array &s) noexcept
Swap this with s
Dynamic singly linked list with functional programming support.
O(1) static range queries via the Cartesian Tree reduction.
constexpr size_t size() const noexcept
Number of elements.
T get(const size_t i) const
Retrieve the value at position i in O(1).
const Gen_Euler_Tour_LCA< T, Comp > & lca_engine() const noexcept
Const reference to the internal LCA engine.
Array< T > values() const
Copy of the original values.
Gen_Cartesian_Tree_RMQ(const DynList< T > &values, Comp c=Comp())
Construct from a DynList<T>.
Gen_Cartesian_Tree_RMQ(const size_t num, const T &init, Comp c=Comp())
Construct with num elements all equal to init.
Gen_Cartesian_Tree_RMQ(const std::vector< T > &values, Comp c=Comp())
Construct from a std::vector<T>.
Gen_Cartesian_Tree_RMQ(std::initializer_list< T > il, Comp c=Comp())
Construct from an initializer_list<T>.
Gen_Cartesian_Tree_RMQ(const Array< T > &values, Comp c=Comp())
Construct from an Array<T>.
T query(const size_t l, const size_t r) const
Range query over [l, r] in O(1).
Gen_Euler_Tour_LCA< T, Comp > lca_
T Item_Type
The type of the element.
size_t query_idx(const size_t l, const size_t r) const
Return the index of the optimal element in a[l..r].
constexpr bool is_empty() const noexcept
True if empty.
Explicit Cartesian Tree built in O(n) with a monotonic stack.
void swap(Gen_Cartesian_Tree &other) noexcept(noexcept(data_.swap(other.data_)) &&noexcept(parent_.swap(other.parent_)) &&noexcept(left_.swap(other.left_)) &&noexcept(right_.swap(other.right_)) &&noexcept(std::swap(root_, other.root_)) &&noexcept(std::swap(n_, other.n_)) &&std::is_nothrow_swappable_v< Comp >)
Swap with other in O(1).
Gen_Cartesian_Tree(std::initializer_list< T > il, Comp c=Comp())
Construct from an initializer_list<T>.
Array< size_t > inorder() const
Inorder traversal of the tree.
T Item_Type
The type of the element stored in the tree.
constexpr size_t root() const noexcept
Index of the root node.
static constexpr size_t NONE
Sentinel value for absent parent/child links.
Array< T > values() const
Copy of the original data array.
const T & data_at(const size_t i) const
Value at node i.
size_t left_child(const size_t i) const
Left child of node i.
void init_and_build()
Initialize arrays of size n with NONE and build.
bool is_leaf(const size_t i) const
True if node i is a leaf (no children).
Gen_Cartesian_Tree(const std::vector< T > &values, Comp c=Comp())
Construct from a std::vector<T>.
Gen_Cartesian_Tree(const Gen_Cartesian_Tree &)=default
Copy constructor.
constexpr size_t size() const noexcept
Number of nodes.
Gen_Cartesian_Tree & operator=(const Gen_Cartesian_Tree &)=default
Copy assignment operator.
size_t parent_of(const size_t i) const
Parent of node i.
Gen_Cartesian_Tree(const Array< T > &values, Comp c=Comp())
Construct from an Array<T>.
Gen_Cartesian_Tree(const size_t num, const T &init, Comp c=Comp())
Construct with num elements all equal to init.
size_t right_child(const size_t i) const
Right child of node i.
void build()
Build the Cartesian Tree using a monotonic stack in O(n).
bool is_root(const size_t i) const
True if node i is the root.
constexpr bool is_empty() const noexcept
True if the tree is empty.
Gen_Cartesian_Tree(const DynList< T > &values, Comp c=Comp())
Construct from a DynList<T>.
size_t height() const
Height of the tree (longest root-to-leaf path).
Gen_Cartesian_Tree(Gen_Cartesian_Tree &&) noexcept(std::is_nothrow_move_constructible_v< Array< T > > and std::is_nothrow_move_constructible_v< Comp >)=default
Lowest Common Ancestor queries in O(1) via Euler Tour reduction to RMQ on a Cartesian Tree.
Gen_Euler_Tour_LCA(std::initializer_list< T > il, Comp c=Comp())
Construct from an initializer_list<T>.
size_t euler_tour_size() const noexcept
Size of the Euler Tour (should be 2n-1 for n > 0).
Gen_Euler_Tour_LCA(const Array< T > &values, Comp c=Comp())
Construct from an Array<T>.
constexpr size_t size() const noexcept
Number of nodes.
void build_sparse_table()
Build the Sparse Table over the depth entries.
Gen_Euler_Tour_LCA(const std::vector< T > &values, Comp c=Comp())
Construct from a std::vector<T>.
const Gen_Cartesian_Tree< T, Comp > & tree() const noexcept
Const reference to the internal Cartesian Tree.
size_t depth_of(const size_t u) const
Depth of node u in the Cartesian Tree.
Array< size_t > depth_arr_
Gen_Euler_Tour_LCA(const size_t num, const T &init, Comp c=Comp())
Construct with num elements all equal to init.
Gen_Euler_Tour_LCA(const DynList< T > &values, Comp c=Comp())
Construct from a DynList<T>.
constexpr bool is_empty() const noexcept
True if empty.
size_t lca(const size_t u, const size_t v) const
Lowest Common Ancestor of nodes u and v in O(1).
size_t distance(const size_t u, const size_t v) const
Distance between nodes u and v in the tree.
Array< size_t > node_depth_
Gen_Cartesian_Tree< T, Comp > tree_
Array< size_t > euler_tour() const
Copy of the Euler Tour array (for inspection/debugging).
Gen_Sparse_Table< DepthEntry, DepthMinOp > sparse_
void build_euler_tour()
Build Euler Tour iteratively using an explicit stack with phases.
Sparse Table over an arbitrary associative and idempotent binary operation.
size_t size() const noexcept
Count the number of elements of the list.
Strict weak ordering constraint for BST comparators.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
static std::atomic< bool > init
Range minimum queries via Cartesian Tree.
Range maximum queries via Cartesian Tree.
Cartesian Tree for min-heap (range minimum).
LCA on a min-heap Cartesian Tree.
Entry for the depth-based Sparse Table: (depth, euler_node_index).
Min-op on DepthEntry: compares by depth.
constexpr DepthEntry operator()(const DepthEntry &a, const DepthEntry &b) const noexcept
Cartesian Tree for max-heap (range maximum).
LCA on a max-heap Cartesian Tree.
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
Sparse Table for static range queries in O(1).