Skip to content

Commit

Permalink
refactor: simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Dec 29, 2024
1 parent dad5cea commit 2ed6269
Show file tree
Hide file tree
Showing 30 changed files with 96 additions and 108 deletions.
28 changes: 21 additions & 7 deletions src/code/ds/hld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
#include "segtree.hpp"

namespace tifa_libs::ds {

template <class T, auto op, auto e, class F = T, auto mapping = op, auto composition = e, auto id = e>
namespace hld_impl_ {
template <bool enable_tag, class T, auto op, class F, auto mapping, auto composition>
class hld {
segtree<T, op, e, F, mapping, composition, id> t;
segtree_impl_::segtree<enable_tag, T, op, F, mapping, composition> t;

public:
using tree_info_t = graph::tree_dfs_info<graph::tree, graph::tdi_dfn, graph::tdi_maxson, graph::tdi_dep, graph::tdi_fa>;
Expand All @@ -19,9 +19,9 @@ class hld {
tree_info_t info;
vecu top;

CEXP hld(graph::tree CR tr, tree_info_t CR info_) : t(), tr(tr), info{info_} { top = graph::tree_top<true>(tr, info.dfn, info.maxson); }
CEXPE hld(graph::tree CR tr) : hld(tr, tree_info_t(tr)) {}
CEXP hld(graph::tree CR tr, tree_info_t CR info_, spn<T> a) : hld(tr, info_) {
CEXP hld(cT_(T) e, cT_(F) id, graph::tree CR tr, tree_info_t CR info_) : t(e, id), tr(tr), info{info_} { top = graph::tree_top<true>(tr, info.dfn, info.maxson); }
CEXP hld(cT_(T) e, cT_(F) id, graph::tree CR tr) : hld(e, id, tr, tree_info_t(tr)) {}
CEXP hld(cT_(T) e, cT_(F) id, graph::tree CR tr, tree_info_t CR info_, spn<T> a) : hld(e, id, tr, info_) {
vec<T> b(a.size());
flt_ (u32, i, 0, (u32)a.size()) b[info.dfn[i]] = a[i];
build(b);
Expand Down Expand Up @@ -50,7 +50,7 @@ class hld {
CEXP void subtree_set(u32 u, cT_(T) f) { t.set(info.dfn[u], info.dfn[u] + info.sz[u], f); }
CEXP void node_set(u32 u, cT_(T) f) { t.set(info.dfn[u] + 1, f); }
CEXP T chain_query(u32 u, u32 v) {
T ret = e();
T ret = t.E;
while (top[u] != top[v]) {
if (info.dep[top[u]] < info.dep[top[v]]) swap(u, v);
ret = op(ret, t.query(info.dfn[top[u]], info.dfn[u] + 1)), u = info.fa[top[u]];
Expand All @@ -61,6 +61,20 @@ class hld {
CEXP T subtree_query(u32 u) { return t.query(info.dfn[u], info.dfn[u] + info.sz[u]); }
CEXP T node_query(u32 u) { return t.query(info.dfn[u]); }
};
} // namespace hld_impl_

template <class T, auto op, class F, auto mapping, auto composition>
using hld = hld_impl_::hld<true, T, op, F, mapping, composition>;
template <class T, auto op>
class hld_notag : public hld_impl_::hld<false, T, op, T, op, op> {
using base = hld_impl_::hld<false, T, op, T, op, op>;

public:
CEXP hld_notag(cT_(T) e, graph::tree CR tr, base::tree_info_t CR info) : base(e, e, tr, info) {}
template <class V>
CEXP hld_notag(cT_(T) e, graph::tree CR tr) : base(e, e, tr) {}
CEXP hld_notag(cT_(T) e, graph::tree CR tr, base::tree_info_t CR info, spn<T> a) : base(e, e, tr, info, a) {}
};

} // namespace tifa_libs::ds

Expand Down
34 changes: 21 additions & 13 deletions src/code/ds/segtree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@

namespace tifa_libs::ds {
namespace segtree_impl_ {
template <bool enable_tag, class T, auto op, auto e, class F, auto mapping, auto composition, auto id>
template <bool enable_tag, class T, auto op, class F, auto mapping, auto composition>
requires requires(T val, T new_val, F tag, F new_tag) {
{ e() } -> std::same_as<T>;
{ op(val, new_val) } -> std::same_as<T>;
{ mapping(val, tag) } -> std::same_as<T>;
{ composition(tag, new_tag) } -> std::same_as<F>;
{ id() } -> std::same_as<F>;
}
class segtree {
const T E; // cannot be static due to dynamic modint
const F ID; // cannot be static due to dynamic modint
struct segtree {
const T E;
const F ID;

private:
u32 sz, lbn, n;
vec<T> val;
vec<F> tag;
vecb vset;

public:
CEXPE segtree() : E(e()), ID(id()), sz(0), lbn(0), n(0), val{}, tag{}, vset{} {}
CEXP segtree(cT_(T) e, cT_(F) id) : E(e), ID(id), sz(0), lbn(0), n(0), val{}, tag{}, vset{} {}
template <class V>
CEXPE segtree(V &&a) : segtree() { reset(std::forward<V>(a)); }
CEXPE segtree(u32 n) : segtree() { reset(vec<T>(n, E)); }
CEXP segtree(cT_(T) e, cT_(F) id, V &&a) : segtree(e, id) { reset(std::forward<V>(a)); }
CEXP segtree(cT_(T) e, cT_(F) id, u32 n) : segtree(e, id) { reset(vec<T>(n, e)); }

template <class V>
CEXP void reset(V &&a) {
Expand Down Expand Up @@ -158,10 +158,18 @@ class segtree {
};
} // namespace segtree_impl_

template <class T, auto op, auto e, class F, auto mapping, auto composition, auto id>
using segtree = segtree_impl_::segtree<true, T, op, e, F, mapping, composition, id>;
template <class T, auto op, auto e>
using segtree_notag = segtree_impl_::segtree<false, T, op, e, T, op, op, e>;
template <class T, auto op, class F, auto mapping, auto composition>
using segtree = segtree_impl_::segtree<true, T, op, F, mapping, composition>;
template <class T, auto op>
class segtree_notag : public segtree_impl_::segtree<false, T, op, T, op, op> {
using base = segtree_impl_::segtree<false, T, op, T, op, op>;

public:
CEXPE segtree_notag(cT_(T) e) : base(e, e) {}
template <class V>
CEXP segtree_notag(cT_(T) e, V &&a) : base(e, e, std::forward<V>(a)) {}
CEXP segtree_notag(cT_(T) e, u32 n) : base(e, e, n) {}
};

} // namespace tifa_libs::ds

Expand Down
26 changes: 10 additions & 16 deletions src/code/ds/segtree_ctor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,24 @@ CEXP P<T> pset_(P<T> CR x, cT_(T) y) { return {x.l * y, x.l}; }
template <class T>
CEXP P<T> padd_(P<T> CR x, cT_(T) y) { return {x.v + x.l * y, x.l}; }
template <class T>
CEXP T e_() { return T(0); }
template <class T, T val>
CEXP T v_() { return val; }
CEXP auto segtl_addmax_ctor(cT_(T) ninf, spn<T> a) { return segtree<T, max_<T>, T, add_<T>, add_<T>>(ninf, T(0), a); }
template <class T>
CEXP P<T> pe_() { return {0, 0}; }
template <class T, T NINF>
CEXP auto segtl_addmax_ctor(spn<T> a) { return segtree<T, max_<T>, v_<T, NINF>, T, add_<T>, add_<T>, e_<T>>(a); }
template <class T, T INF>
CEXP auto segtl_addmin_ctor(spn<T> a) { return segtree<T, min_<T>, v_<T, INF>, T, add_<T>, add_<T>, e_<T>>(a); }
CEXP auto segtl_addmin_ctor(cT_(T) inf, spn<T> a) { return segtree<T, min_<T>, T, add_<T>, add_<T>>(inf, T(0), a); }
template <class T>
CEXP auto segtl_addsum_ctor(vec<T> CR a) {
vec<P<T>> b(a.size());
flt_ (u32, i, 0, (u32)a.size()) b[i] = {a[i], 1};
return segtree<P<T>, add_<P<T>>, pe_<T>, T, padd_<T>, add_<T>, e_<T>>(b);
return segtree<P<T>, add_<P<T>>, T, padd_<T>, add_<T>>(P<T>{0, 0}, T(0), b);
}
template <class T, T NINF>
CEXP auto segtl_setmax_ctor(spn<T> a) { return segtree<T, max_<T>, v_<T, NINF>, T, set_<T>, set_<T>, v_<T, NINF>>(a); }
template <class T, T INF>
CEXP auto segtl_setmin_ctor(spn<T> a) { return segtree<T, min_<T>, v_<T, INF>, T, set_<T>, set_<T>, v_<T, INF>>(a); }
template <class T, T DEF_VAL>
CEXP auto segtl_setsum_ctor(spn<T> a) {
template <class T>
CEXP auto segtl_setmax_ctor(cT_(T) ninf, spn<T> a) { return segtree<T, max_<T>, T, set_<T>, set_<T>>(ninf, ninf, a); }
template <class T>
CEXP auto segtl_setmin_ctor(cT_(T) inf, spn<T> a) { return segtree<T, min_<T>, T, set_<T>, set_<T>>(inf, inf, a); }
template <class T>
CEXP auto segtl_setsum_ctor(cT_(T) def_val, spn<T> a) {
vec<P<T>> b(a.size());
flt_ (u32, i, 0, (u32)a.size()) b[i] = {a[i], 1};
return segtree<P<T>, add_<P<T>>, pe_<T>, T, pset_<T>, set_<T>, v_<T, DEF_VAL>>(b);
return segtree<P<T>, add_<P<T>>, T, pset_<T>, set_<T>>(P<T>{0, 0}, def_val, b);
}
} // namespace segtree_ctor_impl_

Expand Down
4 changes: 2 additions & 2 deletions src/doc_tex/ds/hld.tex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
如果调用构造函数 \verb|hld(tr, info, a)| 或 \verb|hld(tr, a)|, 则 \verb|a| 即输入时点权数组
如果调用构造函数 \verb|hld(e, id, tr, info, a)| 或 \verb|hld(e, id, tr, a)|, 则 \verb|a| 即输入时点权数组

如果调用 \verb|hld(tr, info)| 或 \verb|hld(tr)| 后再 \verb|build(b)|, \verb|b| 为按 dfs 序排序后的数组, 即 \verb|b[dfn[i]] = a[i]|
如果调用 \verb|hld(e, id, tr, info)| 或 \verb|hld(e, id, tr)| 后再 \verb|build(b)|, \verb|b| 为按 dfs 序排序后的数组, 即 \verb|b[dfn[i]] = a[i]|

代码对此有体现
26 changes: 12 additions & 14 deletions src/doc_tex/ds/segtree.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,35 @@

\begin{tabular}{ll}
\hline
代码 & 备注 \\
代码 & 备注 \\
\hline
\verb|class T| & 维护的数据 \\
\verb|T (*op)(T, T)| & 维护的操作 \\
\verb|T (*e)()| & T的幺元 \\
\verb|class T| & 维护的数据 \\
\verb|T (*op)(T, T)| & 维护的操作 \\
\verb|class F| & 修改的类型(会用于lazy标记) \\
\verb|T (*mapping)(T, F) f(x)| & 即修改怎么应用于数据 \\
\verb|F (*composition)(F, F) f(g(x))| & 即修改的复合 \\
\verb|F (*id)() id(x) = x| & 即恒等映射 \\
\verb|F (*composition)(F, F) f(g(x))| & 即修改的复合 \\
\verb|T e| & T的幺元 \\
\verb|F id; id(x) = x| & 即恒等映射 \\
\hline
\end{tabular}

没有区间操作用 \verb|segtree_notag|

\paragraph{例子}

另请参阅 \fullref{sec:常用线段树构造}

\textbf{没有区间操作}

\verb|F = T, maaping = op, id = composition = e|

\textbf{维护}: 区间min; \textbf{操作}: 区间加

\verb|T = {int _min}| 区间和, 长度

\begin{minted}{cpp}
op(T a, T b) = return T{min(a._min, b._min)}
e() = return T{INT_MAX}
F() = {int add}
mapping(T a, F f) = return T{a.s + f.add * a.l, a.l}
composition(F f, F g) = return F{f.add + g.add}
id() = return F{0}
e = T{INT_MAX}
id = F{0}
\end{minted}

\textbf{维护}: 区间和; \textbf{操作}: 区间加,区间乘
Expand All @@ -41,11 +39,11 @@

\begin{minted}{cpp}
op(T a, T b) = return T{a.s + b.s, a.l + b.l}
e() = return T{0, 0}
F() = {mint mul, add}
mapping(T a, F f) = return T{a.s * f.mul + f.add * a.l, a.l}
composition(F f, F g) = return F{f.mul * g.mul, f.mul * g.add + f.add};
// g(x) = g.mul * x + g.add
// f(g(x)) = f.mul * (g.mul * x + g.add) + f.add = f.mul * g.mul * x + f.mul * g.add + f.add
id() = return F{1, 0}
e = T{0, 0}
id = F{1, 0}
\end{minted}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ auto op(T a, T b) { // b(a(x))
tifa_libs::swap(a, b);
return T{a.first * b.first, a.first * b.second + a.second};
}
auto e() { return T{1, 0}; }
auto id() { return e(); }
auto mapping(T a, F f) { return op(f, a); }
auto composition(F, F) { return F(1, 0); }

Expand All @@ -26,7 +24,7 @@ int main() {
std::cin >> n >> q;
vec<T> a(n);
for (auto& x : a) std::cin >> x.first >> x.second;
tifa_libs::ds::segtree<T, op, e, F, mapping, composition, id> seg(a);
tifa_libs::ds::segtree<T, op, F, mapping, composition> seg({1, 0}, {1, 0}, a);
for (u32 i = 0, opt; i < q; ++i) {
std::cin >> opt;
if (opt == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ using T = std::pair<mint, usz>; // sum len
using F = std::pair<mint, mint>; // mul add

auto op(T a, T b) { return T{a.first + b.first, a.second + b.second}; }
auto e() { return T{0, 0}; }
auto mapping(T a, F f) {
return T{f.first * a.first + f.second * a.second, a.second};
}
Expand All @@ -19,7 +18,6 @@ auto composition(F f, F g) {
// g(x) = g.mul * x + g.add
// f(g(x)) = f.mul * (g.mul * x + g.add) + f.add = f.mul * g.mul * x + f.mul * g.add + f.add
}
auto id() { return F{1, 0}; }

int main() {
#define GENTCs_mintd1
Expand All @@ -28,7 +26,7 @@ int main() {
std::cin >> n >> q;
vec<T> a(n);
for (auto &x : a) std::cin >> x.first, x.second = 1;
tifa_libs::ds::segtree<T, op, e, F, mapping, composition, id> segt(a);
tifa_libs::ds::segtree<T, op, F, mapping, composition> segt({0, 0}, {1, 0}, a);
flt_ (u32, i, 1, q + 1) {
u32 opt, l, r;
std::cin >> opt >> l;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ int main() {
for (u32 i = 1, u, v; i < n; ++i) std::cin >> u >> v, tr.add_arc(u, v), tr.add_arc(v, u);
tifa_libs::graph::lca_hld::tree_info_t info(tr);
tifa_libs::graph::lca_hld lca(tr, info);
tifa_libs::ds::hld<T, op_ba, e, F, mapping, composition, id> hld(tr, info, a);
tifa_libs::ds::hld<T, op_ab, e, F, mapping, composition, id> hld1(tr, info, a);
tifa_libs::ds::hld<T, op_ba, F, mapping, composition> hld(e(), id(), tr, info, a);
tifa_libs::ds::hld<T, op_ab, F, mapping, composition> hld1(e(), id(), tr, info, a);
for (u32 i = 0, opt; i < q; ++i) {
std::cin >> opt;
if (opt == 0) {
Expand Down
3 changes: 1 addition & 2 deletions src/test_cpverifier/aizu-dsl/dsl_2_a.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
#include "../../code/ds/segtree.hpp"

u32 op(u32 x, u32 y) { return tifa_libs::min(x, y); }
u32 e() { return 2147483647; }

int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
tifa_libs::ds::segtree_notag<u32, op, e> tr(n);
tifa_libs::ds::segtree_notag<u32, op> tr(2147483647, n);
flt_ (u32, i, 0, q) {
u32 op, u, v;
std::cin >> op >> u >> v;
Expand Down
3 changes: 1 addition & 2 deletions src/test_cpverifier/aizu-dsl/dsl_2_b.segtree.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
#include "../../code/ds/segtree.hpp"

u32 op(u32 x, u32 y) { return x + y; }
u32 e() { return 0; }

int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
tifa_libs::ds::segtree_notag<u32, op, e> tr(n);
tifa_libs::ds::segtree_notag<u32, op> tr(0, n);
flt_ (u32, i, 0, q) {
u32 op, u, v;
std::cin >> op >> u >> v;
Expand Down
2 changes: 1 addition & 1 deletion src/test_cpverifier/aizu-dsl/dsl_2_d.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_setsum_ctor<i64, INT64_MAX>(vecii(n, 2147483647));
auto tr = tifa_libs::ds::segtl_setsum_ctor<i64>(INT64_MAX, vecii(n, 2147483647));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i64 w;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_setmax_ctor<i32, -INT32_MAX>(veci(n, -INT32_MAX));
auto tr = tifa_libs::ds::segtl_setmax_ctor<i32>(-INT32_MAX, veci(n, -INT32_MAX));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i32 w;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_setmin_ctor<i32, INT32_MAX>(veci(n, INT32_MAX));
auto tr = tifa_libs::ds::segtl_setmin_ctor<i32>(INT32_MAX, veci(n, INT32_MAX));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i32 w;
Expand Down
2 changes: 1 addition & 1 deletion src/test_cpverifier/aizu-dsl/dsl_2_h.segtree-addmax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_addmax_ctor<i32, -INT32_MAX>(veci(n));
auto tr = tifa_libs::ds::segtl_addmax_ctor<i32>(-INT32_MAX, veci(n));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i32 w;
Expand Down
2 changes: 1 addition & 1 deletion src/test_cpverifier/aizu-dsl/dsl_2_h.segtree-addmin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_addmin_ctor<i32, INT32_MAX>(veci(n));
auto tr = tifa_libs::ds::segtl_addmin_ctor<i32>(INT32_MAX, veci(n));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i32 w;
Expand Down
2 changes: 1 addition & 1 deletion src/test_cpverifier/aizu-dsl/dsl_2_i.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
auto tr = tifa_libs::ds::segtl_setsum_ctor<i64, -INT32_MAX>(vecii(n));
auto tr = tifa_libs::ds::segtl_setsum_ctor<i64>(-INT32_MAX, vecii(n));
flt_ (u32, i, 0, q) {
u32 op, u, v;
i64 w;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ auto op(T a, T b) { // b(a(x))
tifa_libs::swap(a, b);
return T{a.first * b.first, a.first * b.second + a.second};
}
auto e() { return T{1, 0}; }
auto id() { return e(); }
auto mapping(T a, F f) { return op(f, a); }
auto composition(F, F) { return F(1, 0); }

Expand All @@ -29,7 +27,7 @@ int main() {
std::cin >> n >> q;
vec<T> a(n);
for (auto& x : a) std::cin >> x.first >> x.second;
tifa_libs::ds::segtree<T, op, e, F, mapping, composition, id> seg(a);
tifa_libs::ds::segtree<T, op, F, mapping, composition> seg({1, 0}, {1, 0}, a);
for (u32 i = 0, opt; i < q; ++i) {
std::cin >> opt;
if (opt == 0) {
Expand Down
Loading

0 comments on commit 2ed6269

Please sign in to comment.