89# ifndef TPL_MO_ON_TREES_H
90# define TPL_MO_ON_TREES_H
115 template <
typename GT>
123 typename GT::Node_Arc_Iterator;
124 { g.
vsize() } -> std::convertible_to<size_t>;
126 {
typename GT::Node_Arc_Iterator(p) };
165 template <
class GT,
class Policy>
172 using T =
typename Node::Node_Type;
232 <<
"Gen_Mo_On_Trees: root node not found in graph";
240 for (
auto it =
typename GT::Node_Arc_Iterator(p);
241 it.has_curr(); it.next_ne())
243 auto * a = it.get_curr();
259 for (
size_t i = 0; i <
n_; ++i)
263 for (
size_t i = 0; i <
n_; ++i)
273 visited(root_id) =
true;
285 stk.push({root_id, 0});
287 while (
not stk.is_empty())
289 auto &
fr =
stk.top();
292 while (
fr.child_idx < adj(
fr.id).size())
294 const size_t nid = adj(
fr.id)(
fr.child_idx++);
328 <<
"Gen_Mo_On_Trees: graph is not connected (not a tree)";
332 while ((
static_cast<size_t>(1) <<
log_n_) <
n_)
337 for (
size_t i = 0; i <
log_n_ *
n_; ++i)
340 for (
size_t v = 0; v <
n_; ++v)
344 for (
size_t v = 0; v <
n_; ++v)
351 size_t lca(
size_t u,
size_t v)
const
364 for (
int k =
static_cast<int>(
log_n_) - 1;
k >= 0; --
k)
371 return up_(0 *
n_ + u);
379 const size_t q =
queries.size();
380 const size_t block = std::max<size_t>(
381 1,
static_cast<size_t>(std::sqrt(
static_cast<double>(n))));
386 const size_t ba = a.
l / block;
387 const size_t bb = b.
l / block;
390 return (
ba & 1) ? (a.
r > b.
r) : (a.
r < b.
r);
406 for (
size_t i = 1; i < q; ++i)
487 for (
size_t i = 0; i < q; ++i)
491 <<
"subtree_solve: query " << i <<
" node not in tree";
492 const size_t id = p->second;
511 std::initializer_list<Node*>
il)
const
548 size_t l,
r, id, lca_id;
552 for (
size_t i = 0; i < q; ++i)
557 <<
"path_solve: query " << i <<
" node not in tree";
559 size_t u =
pu->second;
560 size_t v =
pv->second;
573 const size_t block = std::max<size_t>(
574 1,
static_cast<size_t>(
575 std::sqrt(
static_cast<double>(
tour_sz))));
580 const size_t ba = a.l / block;
581 const size_t bb = b.l / block;
584 return (
ba & 1) ? (a.r > b.r) : (a.r < b.r);
591 for (
size_t i = 0; i <
n_; ++i)
595 auto toggle = [&](
const size_t pos)
627 for (
size_t i = 1; i < q; ++i)
663 std::initializer_list<std::pair<Node*, Node*>>
il)
const
698 template <
typename T,
class Policy>
740 if (
root_ ==
nullptr)
748 while (
not stk.is_empty())
757 c = c->get_right_sibling())
782 Node * mp = it.get_curr();
790 for (
size_t pid = 0; pid <
n_; ++pid)
796 c = c->get_right_sibling())
817 for (
size_t i = 0; i <
n_; ++i)
821 for (
size_t i = 0; i <
n_; ++i)
831 visited(root_id) =
true;
843 stk.push({root_id, 0});
845 while (
not stk.is_empty())
847 auto &
fr =
stk.top();
850 while (
fr.child_idx < adj(
fr.id).size())
852 const size_t nid = adj(
fr.id)(
fr.child_idx++);
886 <<
"Gen_Mo_On_Tree_Node: tree traversal inconsistency";
890 while ((
static_cast<size_t>(1) <<
log_n_) <
n_)
895 for (
size_t i = 0; i <
log_n_ *
n_; ++i)
898 for (
size_t v = 0; v <
n_; ++v)
902 for (
size_t v = 0; v <
n_; ++v)
909 size_t lca(
size_t u,
size_t v)
const
922 for (
int k =
static_cast<int>(
log_n_) - 1;
k >= 0; --
k)
929 return up_(0 *
n_ + u);
937 const size_t q =
queries.size();
938 const size_t block = std::max<size_t>(
939 1,
static_cast<size_t>(std::sqrt(
static_cast<double>(
nn))));
944 const size_t ba = a.
l / block;
945 const size_t bb = b.
l / block;
948 return (
ba & 1) ? (a.
r > b.
r) : (a.
r < b.
r);
964 for (
size_t i = 1; i < q; ++i)
999 <<
"Gen_Mo_On_Tree_Node: root is null";
1031 for (
size_t i = 0; i < q; ++i)
1035 <<
"subtree_solve: query " << i <<
" node not in tree";
1036 const size_t id = p->second;
1055 std::initializer_list<Node*>
il)
const
1084 size_t l,
r, id, lca_id;
1088 for (
size_t i = 0; i < q; ++i)
1093 <<
"path_solve: query " << i <<
" node not in tree";
1095 size_t u =
pu->second;
1096 size_t v =
pv->second;
1111 const size_t block = std::max<size_t>(
1112 1,
static_cast<size_t>(
1113 std::sqrt(
static_cast<double>(
tour_sz))));
1118 const size_t ba = a.l / block;
1119 const size_t bb = b.l / block;
1122 return (
ba & 1) ? (a.r > b.r) : (a.r < b.r);
1129 for (
size_t i = 0; i <
n_; ++i)
1132 auto toggle = [&](
const size_t pos)
1137 active(
nid) =
false;
1162 for (
size_t i = 1; i < q; ++i)
1198 std::initializer_list<std::pair<Node*, Node*>>
il)
const
1240 template <
typename T>
1248 template <
typename T>
1256 template <
typename T>
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
T & append()
Allocate a new entry to the end of array.
Dynamic stack of elements of generic type T based on a singly linked list.
T & push(const T &data)
Push an item by copy onto the top of the stack.
Dynamic singly linked list with functional programming support.
T & append(const T &item)
Offline subtree and path queries on N-ary trees (Tree_Node).
static constexpr size_t NONE
Array< answer_type > path_solve(std::initializer_list< std::pair< Node *, Node * > > il) const
Solve path queries (initializer-list overload).
size_t size() const noexcept
Number of nodes in the tree.
size_t lca(size_t u, size_t v) const
MapOLhash< Node *, size_t > node_to_id_
typename Policy::answer_type answer_type
Array< size_t > flat_node_
Array< answer_type > mo_sweep(const Array< T > &data, Array< Mo_Query > queries, size_t nn) const
Array< answer_type > path_solve(const Array< std::pair< Node *, Node * > > &query_pairs) const
Answer path queries on the N-ary tree.
Array< Node * > id_to_node_
Array< answer_type > subtree_solve(std::initializer_list< Node * > il) const
Solve subtree queries (initializer-list overload).
Array< answer_type > subtree_solve(const Array< Node * > &query_roots) const
Answer subtree queries on the N-ary tree.
Gen_Mo_On_Tree_Node(Node *root, Policy p=Policy())
Construct a Mo's algorithm query engine for N-ary trees.
bool is_empty() const noexcept
True if the tree is empty.
Offline subtree and path queries on trees via Mo's algorithm.
typename Policy::answer_type answer_type
typename Node::Node_Type T
Array< answer_type > path_solve(std::initializer_list< std::pair< Node *, Node * > > il) const
Solve path queries (initializer-list overload).
static constexpr size_t NONE
Array< answer_type > subtree_solve(const Array< Node * > &query_roots) const
Answer subtree queries using Mo's algorithm.
Array< Node * > id_to_node_
bool is_empty() const noexcept
True if the tree is empty.
Array< size_t > flat_node_
Array< answer_type > subtree_solve(std::initializer_list< Node * > il) const
Answer subtree queries from an initializer list.
Gen_Mo_On_Trees(const GT &g, Node *root, Policy p=Policy())
Construct a Mo's algorithm query engine for tree queries.
size_t lca(size_t u, size_t v) const
MapOLhash< Node *, size_t > node_to_id_
size_t size() const noexcept
Number of nodes in the tree.
Array< answer_type > mo_sweep(const Array< T > &data, Array< Mo_Query > queries, size_t n) const
Array< answer_type > path_solve(const Array< std::pair< Node *, Node * > > &query_pairs) const
Answer path queries between node pairs.
typename Node::Node_Type Node_Type
The arc class type.
Graph_Node< Node_Info > Node
The graph type.
Graph_Arc< Arc_Info > Arc
The node class type.
Tree_Node * get_left_child() const noexcept
Returns the leftmost child of this.
Tree_Node * get_parent() const noexcept
Returns the parent of this.
T & get_key() noexcept
Returns a modifiable reference to the node contents.
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
constexpr size_t vsize() const noexcept
void for_each_node(Operation &operation) const
Unconditionally traverse all the nodes of graph and on each one perform an operation.
Concept constraining a policy for Mo's algorithm.
Concept constraining a graph type usable for Mo on Trees.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
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.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
Policy: count distinct elements in a range.
Open addressing hash map using linear probing.
Data & find(const Key &key)
Find and return the value for a key.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair (copy semantics).
Pair * search(const Key &key) const noexcept
Search for a key in the map.
A query for Mo's algorithm: inclusive range [l, r] with id.
size_t l
Left endpoint (inclusive, 0-based).
size_t r
Right endpoint (inclusive, 0-based).
Policy: "powerful array" sum = sum(cnt[x]^2 * x).
Policy: range mode (most frequent element).
Dynamic array container with automatic resizing.
Dynamic stack implementation based on linked lists.
Alias for htlist.H (DynList implementation).
Dynamic map with open hashing.
Mo's algorithm for offline range queries.
General tree (n-ary tree) node.