62# ifndef TPL_SEGMENT_TREE_H
63# define TPL_SEGMENT_TREE_H
68# include <initializer_list>
70# include <type_traits>
99 template <
typename F,
typename T>
101 requires(
const F& f,
const T& a,
const T& b)
103 { f(a, b) } -> std::convertible_to<T>;
146 template <
typename T,
class Op>
155 void build(
size_t node,
const size_t start,
const size_t end)
160 const size_t mid = start + (end - start) / 2;
166 void update_impl(
size_t node,
const size_t start,
const size_t end,
167 const size_t idx,
const T & delta)
175 if (
const size_t mid = start + (end - start) / 2; idx <=
mid)
183 void set_impl(
size_t node,
const size_t start,
const size_t end,
184 const size_t idx,
const T & val)
192 if (
const size_t mid = start + (end - start) / 2; idx <=
mid)
201 const size_t l,
const size_t r)
const
203 if (
r < start || end <
l)
206 if (
l <= start
and end <=
r)
209 const size_t mid = start + (end - start) / 2;
214 template <
class Getter>
224 template <
class Getter>
234 const size_t mid = start + (end - start) / 2;
239 template <
class AlephIt>
244 for (; it.has_curr(); it.next_ne())
245 tmp(i++) = it.get_curr();
263 const T &
id, Op
oper = Op())
264 :
tree(num == 0 ? 1 : 4 * num, id),
284 const T &
id, Op
oper = Op())
290 auto it =
il.begin();
302 const T &
id, Op
oper = Op())
317 const T &
id, Op
oper = Op())
332 const T &
id, Op
oper = Op())
361 <<
"Gen_Segment_Tree::update: index " << i <<
" >= size " <<
n;
372 void set(
const size_t i,
const T & val)
375 <<
"Gen_Segment_Tree::set: index " << i <<
" >= size " <<
n;
392 <<
"Gen_Segment_Tree::query: r=" <<
r <<
" >= n=" <<
n;
394 <<
"Gen_Segment_Tree::query: l=" <<
l <<
" > r=" <<
r;
409 <<
"Gen_Segment_Tree::get: index " << i <<
" >= size " <<
n;
427 for (
size_t i = 0; i <
n; ++i)
434 noexcept(std::swap(std::declval<T&>(), std::declval<T&>()))
and
435 noexcept(std::swap(std::declval<Op&>(), std::declval<Op&>())))
462 template <
typename T>
535 template <std::totally_ordered T>
548 const T &
init_val = std::numeric_limits<T>::max())
610 template <std::totally_ordered T>
623 const T &
init_val = std::numeric_limits<T>::lowest())
694 template <
typename P>
696 std::equality_comparable<typename P::lazy_type>
and
698 const typename P::value_type& v1,
699 const typename P::value_type& v2,
700 const typename P::lazy_type&
lz1,
701 const typename P::lazy_type&
lz2,
704 typename P::value_type;
705 typename P::lazy_type;
706 { p.combine(v1, v2) } -> std::convertible_to<typename P::value_type>;
707 { p.apply(v1,
lz1,
count) } -> std::convertible_to<typename P::value_type>;
708 { p.compose(
lz1,
lz2) } -> std::convertible_to<typename P::lazy_type>;
709 { p.value_identity() } -> std::convertible_to<typename P::value_type>;
710 { p.lazy_identity() } -> std::convertible_to<typename P::lazy_type>;
726 template <
typename T>
732 static constexpr T combine(
const T & a,
const T & b)
noexcept
737 static constexpr T apply(
const T & val,
const T & delta,
738 size_t count)
noexcept
740 return val + delta *
static_cast<T>(
count);
766 template <std::totally_ordered T>
772 static constexpr T combine(
const T & a,
const T & b)
noexcept
774 return a <= b ? a : b;
777 static constexpr T apply(
const T & val,
const T & delta,
791 return std::numeric_limits<T>::max();
810 template <std::totally_ordered T>
816 static constexpr T combine(
const T & a,
const T & b)
noexcept
818 return a >= b ? a : b;
821 static constexpr T apply(
const T & val,
const T & delta,
835 return std::numeric_limits<T>::lowest();
860 template <
typename T>
866 static constexpr T combine(
const T & a,
const T & b)
noexcept
872 size_t count)
noexcept
874 return lz.first ?
lz.second *
static_cast<T>(
count) : val;
920 template <
typename Policy>
935 void push_down(
size_t node,
const size_t start,
const size_t end)
const
937 if (
lazy(node) ==
pol.lazy_identity())
940 const size_t mid = start + (end - start) / 2;
941 const size_t left = 2 * node;
942 const size_t right = 2 * node + 1;
950 lazy(node) =
pol.lazy_identity();
953 void build(
size_t node,
const size_t start,
const size_t end)
958 const size_t mid = start + (end - start) / 2;
964 void update_impl(
size_t node,
const size_t start,
const size_t end,
965 const size_t l,
const size_t r,
const lazy_type & val)
967 if (
r < start
or end <
l)
970 if (
l <= start
and end <=
r)
972 tree(node) =
pol.apply(
tree(node), val, end - start + 1);
979 const size_t mid = start + (end - start) / 2;
986 const size_t l,
const size_t r)
const
988 if (
r < start
or end <
l)
989 return pol.value_identity();
991 if (
l <= start
and end <=
r)
996 const size_t mid = start + (end - start) / 2;
1002 void set_impl(
size_t node,
const size_t start,
const size_t end,
1008 lazy(node) =
pol.lazy_identity();
1014 if (
const size_t mid = start + (end - start) / 2; idx <=
mid)
1022 template <
class Getter>
1029 template <
class Getter>
1039 const size_t mid = start + (end - start) / 2;
1044 template <
class AlephIt>
1049 for (; it.has_curr(); it.next_ne())
1050 tmp(i++) = it.get_curr();
1058 return n == 0 ? 1 : 4 *
n;
1066 :
tree(num == 0 ? 1 : 4 * num, p.value_identity()),
1067 lazy(num == 0 ? 1 : 4 * num, p.lazy_identity()),
1146 <<
"Gen_Lazy_Segment_Tree::update: r=" <<
r <<
" >= n=" <<
n;
1148 <<
"Gen_Lazy_Segment_Tree::update: l=" <<
l <<
" > r=" <<
r;
1173 <<
"Gen_Lazy_Segment_Tree::set: index " << i <<
" >= size " <<
n;
1192 <<
"Gen_Lazy_Segment_Tree::query: r=" <<
r <<
" >= n=" <<
n;
1194 <<
"Gen_Lazy_Segment_Tree::query: l=" <<
l <<
" > r=" <<
r;
1221 for (
size_t i = 0; i <
n; ++i)
1228 noexcept(std::swap(std::declval<Policy&>(), std::declval<Policy&>())))
1242 template <
typename T>
1258 template <std::totally_ordered T>
1274 template <std::totally_ordered T>
1314 template <
typename T>
1315 requires std::is_arithmetic_v<T>
and std::is_signed_v<T>
1328 static constexpr T INF = std::numeric_limits<T>::max();
1329 static constexpr T NEG_INF = std::numeric_limits<T>::lowest();
1339 const auto &
l =
tree(2 * node);
1340 const auto &
r =
tree(2 * node + 1);
1342 tree(node).sum =
l.sum +
r.sum;
1345 if (
l.max_val >
r.max_val)
1347 tree(node).max_val =
l.max_val;
1348 tree(node).count_max =
l.count_max;
1349 tree(node).second_max = std::max(
l.second_max,
r.max_val);
1351 else if (
l.max_val <
r.max_val)
1353 tree(node).max_val =
r.max_val;
1354 tree(node).count_max =
r.count_max;
1355 tree(node).second_max = std::max(
l.max_val,
r.second_max);
1359 tree(node).max_val =
l.max_val;
1360 tree(node).count_max =
l.count_max +
r.count_max;
1361 tree(node).second_max = std::max(
l.second_max,
r.second_max);
1365 if (
l.min_val <
r.min_val)
1367 tree(node).min_val =
l.min_val;
1368 tree(node).count_min =
l.count_min;
1369 tree(node).second_min = std::min(
l.second_min,
r.min_val);
1371 else if (
l.min_val >
r.min_val)
1373 tree(node).min_val =
r.min_val;
1374 tree(node).count_min =
r.count_min;
1375 tree(node).second_min = std::min(
l.min_val,
r.second_min);
1379 tree(node).min_val =
l.min_val;
1380 tree(node).count_min =
l.count_min +
r.count_min;
1381 tree(node).second_min = std::min(
l.second_min,
r.second_min);
1391 if (v >=
nd.max_val)
1394 nd.sum -=
static_cast<T>(
nd.count_max) * (
nd.max_val - v);
1398 if (
nd.min_val ==
nd.max_val)
1400 if (
nd.second_min ==
nd.max_val)
1406 nd.lazy_chmin = std::min(
nd.lazy_chmin, v);
1407 nd.lazy_chmax = std::min(
nd.lazy_chmax, v);
1413 if (v <=
nd.min_val)
1416 nd.sum +=
static_cast<T>(
nd.count_min) * (v -
nd.min_val);
1419 if (
nd.max_val ==
nd.min_val)
1421 if (
nd.second_max ==
nd.min_val)
1427 nd.lazy_chmax = std::max(
nd.lazy_chmax, v);
1428 nd.lazy_chmin = std::max(
nd.lazy_chmin, v);
1444 if (
nd.lazy_chmin !=
INF)
1448 nd.lazy_chmin =
INF;
1452 void build(
size_t node,
size_t start,
size_t end)
1457 const size_t mid = start + (end - start) / 2;
1463 void chmin_impl(
size_t node,
const size_t start,
const size_t end,
1464 const size_t l,
const size_t r,
T v)
1466 if (
r < start
or end <
l or tree(node).max_val <= v)
1469 if (
l <= start
and end <=
r and tree(node).second_max < v)
1476 const size_t mid = start + (end - start) / 2;
1482 void chmax_impl(
size_t node,
const size_t start,
const size_t end,
1483 const size_t l,
const size_t r,
T v)
1485 if (
r < start
or end <
l or tree(node).min_val >= v)
1488 if (
l <= start
and end <=
r and tree(node).second_min > v)
1495 const size_t mid = start + (end - start) / 2;
1502 const size_t l,
const size_t r)
const
1504 if (
r < start
or end <
l)
1507 if (
l <= start
and end <=
r)
1508 return tree(node).sum;
1511 const size_t mid = start + (end - start) / 2;
1517 const size_t l,
const size_t r)
const
1519 if (
r < start
or end <
l)
1522 if (
l <= start
and end <=
r)
1523 return tree(node).max_val;
1526 const size_t mid = start + (end - start) / 2;
1532 const size_t l,
const size_t r)
const
1534 if (
r < start
or end <
l)
1537 if (
l <= start
and end <=
r)
1538 return tree(node).min_val;
1541 const size_t mid = start + (end - start) / 2;
1546 template <
class Getter>
1553 template <
class Getter>
1563 const size_t mid = start + (end - start) / 2;
1572 for (
size_t i = 0; i <
tree.size(); ++i)
1605 auto it =
il.begin();
1652 for (
auto it =
values.get_it(); it.has_curr(); it.next_ne())
1653 tmp(i++) = it.get_curr();
1672 <<
"Segment_Tree_Beats::chmin: r=" <<
r <<
" >= n=" <<
n;
1674 <<
"Segment_Tree_Beats::chmin: l=" <<
l <<
" > r=" <<
r;
1683 void chmax(
const size_t l,
const size_t r,
const T & v)
1686 <<
"Segment_Tree_Beats::chmax: r=" <<
r <<
" >= n=" <<
n;
1688 <<
"Segment_Tree_Beats::chmax: l=" <<
l <<
" > r=" <<
r;
1700 <<
"Segment_Tree_Beats::query_sum: r=" <<
r <<
" >= n=" <<
n;
1702 <<
"Segment_Tree_Beats::query_sum: l=" <<
l <<
" > r=" <<
r;
1714 <<
"Segment_Tree_Beats::query_max: r=" <<
r <<
" >= n=" <<
n;
1716 <<
"Segment_Tree_Beats::query_max: l=" <<
l <<
" > r=" <<
r;
1728 <<
"Segment_Tree_Beats::query_min: r=" <<
r <<
" >= n=" <<
n;
1730 <<
"Segment_Tree_Beats::query_min: l=" <<
l <<
" > r=" <<
r;
1751 for (
size_t i = 0; i <
n; ++i)
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.
Lazy segment tree with range update and range query.
void build(size_t node, const size_t start, const size_t end)
void point_update(const size_t i, const lazy_type &delta)
Point update: apply delta to a[i].
Gen_Lazy_Segment_Tree(const Array< value_type > &values, Policy p=Policy())
Construct from an Array<value_type>.
void set_impl(size_t node, const size_t start, const size_t end, const size_t idx, const value_type &val)
Gen_Lazy_Segment_Tree(const std::vector< value_type > &values, Policy p=Policy())
Construct from a std::vector.
constexpr size_t size() const noexcept
Number of logical elements.
void update_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r, const lazy_type &val)
void fill_and_build(Getter getter)
typename Policy::value_type value_type
value_type query(const size_t l, const size_t r) const
Range query over [l, r].
constexpr bool is_empty() const noexcept
True if the tree contains no elements.
Array< value_type > values() const
Reconstruct all original values into an Array.
Gen_Lazy_Segment_Tree(const DynList< value_type > &values, Policy p=Policy())
Construct from a DynList.
void update(const size_t l, const size_t r, const lazy_type &val)
Range update: apply val to every a[i] with l <= i <= r.
void set(const size_t i, const value_type &val)
Set a[i] = val.
value_type query_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r) const
typename Policy::lazy_type lazy_type
void swap(Gen_Lazy_Segment_Tree &other) noexcept(noexcept(std::swap(std::declval< Policy & >(), std::declval< Policy & >())))
Swap this tree with other in O(1).
Gen_Lazy_Segment_Tree(std::initializer_list< value_type > il, Policy p=Policy())
Construct from an initializer list.
void fill_from_aleph_it(AlephIt it)
size_t alloc_size() const
Gen_Lazy_Segment_Tree(const size_t num, const value_type &init_val=value_type(), Policy p=Policy())
Construct with num elements, all equal to init_val.
Gen_Lazy_Segment_Tree(const Gen_Lazy_Segment_Tree &)=default
void fill_leaves_recursive(size_t node, size_t start, size_t end, Getter &getter)
void push_down(size_t node, const size_t start, const size_t end) const
value_type get(const size_t i) const
Retrieve the value a[i].
Gen_Lazy_Segment_Tree(Gen_Lazy_Segment_Tree &&) noexcept(std::is_nothrow_move_constructible_v< Array< value_type > > and std::is_nothrow_move_constructible_v< Array< lazy_type > > and std::is_nothrow_move_constructible_v< Policy >)=default
Segment tree over an arbitrary associative binary operation.
void set(const size_t i, const T &val)
Set a[i] = val.
void update_impl(size_t node, const size_t start, const size_t end, const size_t idx, const T &delta)
void swap(Gen_Segment_Tree &other) noexcept(noexcept(std::swap(std::declval< T & >(), std::declval< T & >())) and noexcept(std::swap(std::declval< Op & >(), std::declval< Op & >())))
Swap this tree with other in O(1).
T query(const size_t l, const size_t r) const
Range query over [l, r].
Gen_Segment_Tree(const size_t num, const T &init_val, const T &id, Op oper=Op())
Construct a segment tree with num elements, all equal to init_val.
Gen_Segment_Tree(const Array< T > &values, const T &id, Op oper=Op())
Construct from an Array<T>.
void set_impl(size_t node, const size_t start, const size_t end, const size_t idx, const T &val)
Gen_Segment_Tree(const DynList< T > &values, const T &id, Op oper=Op())
Construct from a DynList<T>.
void fill_from_aleph_it(AlephIt it)
void fill_leaves_recursive(size_t node, size_t start, size_t end, Getter &getter)
T query_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r) const
Gen_Segment_Tree(std::initializer_list< T > il, const T &id, Op oper=Op())
Construct from an initializer list.
Gen_Segment_Tree(const Gen_Segment_Tree &)=default
void fill_and_build(Getter getter)
constexpr bool is_empty() const noexcept
True if the tree contains no elements.
Array< T > values() const
Reconstruct all original values into an Array.
T get(const size_t i) const
Retrieve the value a[i].
void update(const size_t i, const T &delta)
Point update: a[i] = Op(a[i], delta).
Gen_Segment_Tree(Gen_Segment_Tree &&) noexcept(std::is_nothrow_move_constructible_v< Array< T > > and std::is_nothrow_move_constructible_v< Op >)=default
constexpr size_t size() const noexcept
Number of logical elements.
void build(size_t node, const size_t start, const size_t end)
Gen_Segment_Tree(const std::vector< T > &values, const T &id, Op oper=Op())
Construct from a std::vector<T>.
Ji Driver's Segment Tree (Segment Tree Beats).
void chmax_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r, T v)
void chmax(const size_t l, const size_t r, const T &v)
Range chmax: for each i in [l, r], set a[i] = max(a[i], v).
constexpr size_t size() const noexcept
Number of logical elements.
T query_min_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r) const
T query_sum(const size_t l, const size_t r) const
Range sum query over [l, r].
static constexpr T NEG_INF
T get(const size_t i) const
Retrieve the value at position i.
void build(size_t node, size_t start, size_t end)
T query_max_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r) const
T query_max(const size_t l, const size_t r) const
Range max query over [l, r].
void push_chmin_to_child(size_t child, T v) const
Segment_Tree_Beats(const Array< T > &values)
Construct from an Array<T>.
void fill_and_build(Getter getter)
Segment_Tree_Beats(const size_t num, const T &init_val=T())
Construct with num elements, all equal to init_val.
Segment_Tree_Beats(Segment_Tree_Beats &&) noexcept(std::is_nothrow_move_constructible_v< Array< Node > >)=default
Segment_Tree_Beats(const Segment_Tree_Beats &)=default
Segment_Tree_Beats(const std::vector< T > &values)
Construct from a std::vector<T>.
void push_chmax_to_child(size_t child, T v) const
void chmin(const size_t l, const size_t r, const T &v)
Range chmin: for each i in [l, r], set a[i] = min(a[i], v).
void push_down(size_t node) const
void chmin_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r, T v)
Array< T > values() const
Reconstruct all values into an Array.
T query_min(const size_t l, const size_t r) const
Range min query over [l, r].
void swap(Segment_Tree_Beats &other) noexcept
Swap this tree with other in O(1).
constexpr bool is_empty() const noexcept
True if the tree contains no elements.
void pull_up(size_t node) const
void fill_leaves_recursive(const size_t node, size_t start, size_t end, Getter &getter)
T query_sum_impl(size_t node, const size_t start, const size_t end, const size_t l, const size_t r) const
void init_leaf(size_t node, const T &val)
Segment_Tree_Beats(std::initializer_list< T > il)
Construct from an initializer list.
Segment_Tree_Beats(const DynList< T > &values)
Construct from a DynList<T>.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Binary operation compatible with Segment Tree queries.
Policy concept for lazy segment tree.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
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
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Range add + range max policy.
static constexpr T compose(const T &old_lazy, const T &new_lazy) noexcept
static constexpr T lazy_identity() noexcept
constexpr T value_identity() const noexcept
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T apply(const T &val, const T &delta, size_t) noexcept
Range add + range min policy.
static constexpr T lazy_identity() noexcept
static constexpr T compose(const T &old_lazy, const T &new_lazy) noexcept
constexpr T value_identity() const noexcept
static constexpr T apply(const T &val, const T &delta, size_t) noexcept
static constexpr T combine(const T &a, const T &b) noexcept
Range add + range sum policy.
static constexpr T value_identity() noexcept
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T apply(const T &val, const T &delta, size_t count) noexcept
static constexpr T lazy_identity() noexcept
static constexpr T compose(const T &old_lazy, const T &new_lazy) noexcept
Range assign + range sum policy.
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T value_identity() noexcept
static constexpr lazy_type lazy_identity() noexcept
std::pair< bool, T > lazy_type
static constexpr T apply(const T &val, const lazy_type &lz, size_t count) noexcept
static constexpr lazy_type compose(const lazy_type &old_lz, const lazy_type &new_lz) noexcept
Lazy segment tree for range add + range max.
Lazy segment tree for range add + range min.
Lazy segment tree for range add + range sum.
Max Segment Tree for range maximum queries with point updates.
Max_Segment_Tree(const size_t num, const T &init_val=std::numeric_limits< T >::lowest())
Construct with num elements, all equal to init_val.
Max_Segment_Tree(const DynList< T > &values)
Construct from a DynList<T>.
Max_Segment_Tree(const std::vector< T > &values)
Construct from a std::vector<T>.
Max_Segment_Tree(std::initializer_list< T > il)
Construct from an initializer list.
Max_Segment_Tree(const Array< T > &values)
Construct from an Array<T>.
Min Segment Tree for range minimum queries with point updates.
Min_Segment_Tree(const size_t num, const T &init_val=std::numeric_limits< T >::max())
Construct with num elements, all equal to init_val.
Min_Segment_Tree(const std::vector< T > &values)
Construct from a std::vector<T>.
Min_Segment_Tree(const DynList< T > &values)
Construct from a DynList<T>.
Min_Segment_Tree(const Array< T > &values)
Construct from an Array<T>.
Min_Segment_Tree(std::initializer_list< T > il)
Construct from an initializer list.
Sum Segment Tree for range sum queries with point updates.
Sum_Segment_Tree(const DynList< T > &values)
Construct from a DynList<T>.
Sum_Segment_Tree(const size_t num, const T &init_val=T())
Construct with num elements, all equal to init_val.
Sum_Segment_Tree(const std::vector< T > &values)
Construct from a std::vector<T>.
Sum_Segment_Tree(const Array< T > &values)
Construct from an Array<T>.
Sum_Segment_Tree(std::initializer_list< T > il)
Construct from an initializer list.
Dynamic array container with automatic resizing.
Alias for htlist.H (DynList implementation).
Sparse Table for static range queries in O(1).