From fd4072ecec947f542db171b7d2a4e174899a6767 Mon Sep 17 00:00:00 2001 From: NyaanNyaan Date: Fri, 3 May 2024 21:06:15 +0900 Subject: [PATCH] add misc --- .vscode/settings.json | 17 ++- .../rectangle-add-rectangle-sum.hpp | 90 +++++++++++++ geometry/integer-geometry.hpp | 7 +- geometry/polygon.hpp | 5 +- graph/functional-graph.hpp | 127 ++++++++++++++++++ graph/{funtional-graph.hpp => namori.hpp} | 0 math/affine-transformation.hpp | 3 +- matrix/gauss-elimination.hpp | 1 + ntt/multiplicative-convolution-mod-p.hpp | 30 +++++ tree/static-top-tree-vertex-based.hpp | 8 +- verify/verify-aoj-other/aoj-2891-2.test.cpp | 33 +++++ verify/verify-aoj-other/aoj-2891.test.cpp | 2 +- .../yosupo-range-set-range-composite.test.cpp | 56 ++++++++ ...tatic-rectangle-add-rectangle-sum.test.cpp | 36 +++++ ...e-path-composite-sum-fixed-root-2.test.cpp | 69 ++++++++++ ...ree-path-composite-sum-fixed-root.test.cpp | 77 +++++++++++ ...point-set-tree-path-composite-sum.test.cpp | 70 ++++++++++ .../yosupo-pow-of-matrix-2.test.cpp | 31 +++++ .../yosupo-pow-of-matrix.test.cpp | 31 +++++ .../yosupo-rank-of-matrix.test.cpp | 36 +++++ .../yosupo-rational-approximation.test.cpp | 26 ++++ .../yosupo-convolution-on-z-pz.test.cpp | 30 +++++ .../yosupo-static-convex-hull-2.test.cpp | 21 +++ .../yosupo-static-convex-hull.test.cpp | 21 +++ verify/verify-yuki/yuki-1254-2.test.cpp | 46 +++++++ verify/verify-yuki/yuki-1254.test.cpp | 2 +- 26 files changed, 861 insertions(+), 14 deletions(-) create mode 100644 data-structure-2d/rectangle-add-rectangle-sum.hpp create mode 100644 graph/functional-graph.hpp rename graph/{funtional-graph.hpp => namori.hpp} (100%) create mode 100644 ntt/multiplicative-convolution-mod-p.hpp create mode 100644 verify/verify-aoj-other/aoj-2891-2.test.cpp create mode 100644 verify/verify-yosupo-ds/yosupo-range-set-range-composite.test.cpp create mode 100644 verify/verify-yosupo-ds/yosupo-static-rectangle-add-rectangle-sum.test.cpp create mode 100644 verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root-2.test.cpp create mode 100644 verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root.test.cpp create mode 100644 verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum.test.cpp create mode 100644 verify/verify-yosupo-math/yosupo-pow-of-matrix-2.test.cpp create mode 100644 verify/verify-yosupo-math/yosupo-pow-of-matrix.test.cpp create mode 100644 verify/verify-yosupo-math/yosupo-rank-of-matrix.test.cpp create mode 100644 verify/verify-yosupo-math/yosupo-rational-approximation.test.cpp create mode 100644 verify/verify-yosupo-ntt/yosupo-convolution-on-z-pz.test.cpp create mode 100644 verify/verify-yosupo-other/yosupo-static-convex-hull-2.test.cpp create mode 100644 verify/verify-yosupo-other/yosupo-static-convex-hull.test.cpp create mode 100644 verify/verify-yuki/yuki-1254-2.test.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 46fabaf9b..168552a30 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -82,14 +82,27 @@ "cfloat": "cpp", "barrier": "cpp", "latch": "cpp", - "semaphore": "cpp" + "semaphore": "cpp", + "stack": "cpp", + "any": "cpp", + "variant": "cpp", + "expected": "cpp", + "spanstream": "cpp", + "stop_token": "cpp", + "syncstream": "cpp", + "source_location": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "coroutine": "cpp", + "numbers": "cpp" }, "C_Cpp.suggestSnippets": false, "[cpp]": { "editor.tabSize": 2 }, "[python]": { - "editor.tabSize": 2, + "editor.tabSize": 4, "editor.formatOnSave": false, "editor.formatOnPaste": false, "editor.formatOnType": false, diff --git a/data-structure-2d/rectangle-add-rectangle-sum.hpp b/data-structure-2d/rectangle-add-rectangle-sum.hpp new file mode 100644 index 000000000..66ac7ef3b --- /dev/null +++ b/data-structure-2d/rectangle-add-rectangle-sum.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include +using namespace std; + +#include "../data-structure/binary-indexed-tree.hpp" + +// https://hitonanode.github.io/cplib-cpp/data_structure/rectangle_add_rectangle_sum.hpp +template +class RectangleAddRectangleSum { + struct AddQuery { + I xl, xr, yl, yr; + T val; + }; + struct SumQuery { + I xl, xr, yl, yr; + }; + vector add_queries; + vector sum_queries; + + public: + RectangleAddRectangleSum() = default; + + void add_rectangle(I xl, I xr, I yl, I yr, T val) { + add_queries.push_back(AddQuery{xl, xr, yl, yr, val}); + } + void add_query(I xl, I xr, I yl, I yr) { + sum_queries.push_back(SumQuery{xl, xr, yl, yr}); + } + + vector solve() const { + vector ys; + for (const auto &a : add_queries) { + ys.push_back(a.yl); + ys.push_back(a.yr); + } + sort(ys.begin(), ys.end()); + ys.erase(unique(ys.begin(), ys.end()), ys.end()); + + const int Y = ys.size(); + + vector> ops; + for (int q = 0; q < int(sum_queries.size()); ++q) { + ops.emplace_back(sum_queries[q].xl, 0, q); + ops.emplace_back(sum_queries[q].xr, 1, q); + } + for (int q = 0; q < int(add_queries.size()); ++q) { + ops.emplace_back(add_queries[q].xl, 2, q); + ops.emplace_back(add_queries[q].xr, 3, q); + } + sort(ops.begin(), ops.end()); + + BinaryIndexedTree b00(Y), b01(Y), b10(Y), b11(Y); + vector ret(sum_queries.size()); + for (auto o : ops) { + int qtype = get<1>(o), q = get<2>(o); + if (qtype >= 2) { + const AddQuery &query = add_queries.at(q); + int i = lower_bound(ys.begin(), ys.end(), query.yl) - ys.begin(); + int j = lower_bound(ys.begin(), ys.end(), query.yr) - ys.begin(); + T x = get<0>(o); + T yi = query.yl, yj = query.yr; + if (qtype & 1) swap(i, j), swap(yi, yj); + + b00.add(i, x * yi * query.val); + b01.add(i, -x * query.val); + b10.add(i, -yi * query.val); + b11.add(i, query.val); + b00.add(j, -x * yj * query.val); + b01.add(j, x * query.val); + b10.add(j, yj * query.val); + b11.add(j, -query.val); + } else { + const SumQuery &query = sum_queries.at(q); + int i = lower_bound(ys.begin(), ys.end(), query.yl) - ys.begin(); + int j = lower_bound(ys.begin(), ys.end(), query.yr) - ys.begin(); + T x = get<0>(o); + T yi = query.yl, yj = query.yr; + if (qtype & 1) swap(i, j), swap(yi, yj); + + i--, j--; + ret[q] += + b00.sum(i) + b01.sum(i) * yi + b10.sum(i) * x + b11.sum(i) * x * yi; + ret[q] -= + b00.sum(j) + b01.sum(j) * yj + b10.sum(j) * x + b11.sum(j) * x * yj; + } + } + return ret; + } +}; diff --git a/geometry/integer-geometry.hpp b/geometry/integer-geometry.hpp index cd07c287f..1cf9d4140 100644 --- a/geometry/integer-geometry.hpp +++ b/geometry/integer-geometry.hpp @@ -89,9 +89,10 @@ Points UpperHull(const Points &ps) { return convex; } -Points ConvexHull(const Points &ps) { - int N = (int)ps.size(); - for (int i = 0; i < N - 1; i++) assert(ps[i].x <= ps[i + 1].x); +Points ConvexHull(Points ps) { + sort(begin(ps), end(ps)); + ps.erase(unique(begin(ps), end(ps)), end(ps)); + int N = ps.size(); if (N <= 2) return ps; Points convex(2 * N); int k = 0; diff --git a/geometry/polygon.hpp b/geometry/polygon.hpp index 26fad2451..0ff230f7a 100644 --- a/geometry/polygon.hpp +++ b/geometry/polygon.hpp @@ -31,9 +31,10 @@ Real area(const Polygon &p) { // boundary : 周上の点も列挙する場合 true template Polygon convex_hull(vector ps) { - int n = (int)ps.size(), k = 0; + sort(begin(ps), end(ps)); + ps.erase(unique(begin(ps), end(ps)), end(ps)); + int n = ps.size(), k = 0; if (n <= 2) return ps; - sort(ps.begin(), ps.end()); vector ch(2 * n); // 反時計周り Real th = boundary ? -EPS : +EPS; diff --git a/graph/functional-graph.hpp b/graph/functional-graph.hpp new file mode 100644 index 000000000..da7bd63f0 --- /dev/null +++ b/graph/functional-graph.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include +#include +#include +using namespace std; + +#include "../data-structure/union-find.hpp" +#include "../internal/internal-type-traits.hpp" +#include "graph-template.hpp" + +namespace FunctionalGraphImpl { + +ENABLE_HAS_VAR(cost) + +template +struct FunctionalGraph { + int N; + WeightedGraph g; + vector to, represent; + vector weight; + + FunctionalGraph() = default; + + FunctionalGraph(int n, const vector& adj, + const vector& w = vector{}) + : N(n), g(N + 1), to(N + 1, -1), represent(N + 1, -1), weight(N + 1) { + assert((int)adj.size() == N); + assert((int)w.size() == N or w.empty()); + for (auto& x : adj) assert(0 <= x and x < N); + + UnionFind uf(N); + for (int i = 0; i < N; i++) { + int j = adj[i]; + to[i] = j, weight[i] = w.empty() ? T{1} : w[i]; + if (uf.same(i, j)) { + g[N].emplace_back(N, i, weight[i]); + } else { + uf.unite(i, j); + g[j].emplace_back(j, i, weight[i]); + } + } + calc_represent(N, -1); + } + + // _g は無向グラフ + template + FunctionalGraph(int n, const G& _g) + : N(n), g(N + 1), to(N + 1, -1), represent(N + 1, -1), weight(N + 1) { + constexpr bool cost_flag = has_cost_v; + WeightedGraph h(n); + UnionFind uf(N); + for (int i = 0; i < N; i++) { + for (auto& j : _g[i]) { + if (i > j) continue; + T cost; + if constexpr (cost_flag) { + cost = j.cost; + } else { + cost = 1; + } + if (uf.same(i, j)) { + // i -> j 向きということにして, i を根とする + g[N].emplace_back(N, i, 0); + to[i] = j, weight[i] = cost; + } else { + uf.unite(i, j); + h[i].emplace_back(i, j, cost); + h[j].emplace_back(j, i, cost); + } + } + } + + auto dfs = [&](auto rc, int c, int p) -> void { + for (auto& d : h[c]) { + if (d == p) continue; + T cost; + if constexpr (cost_flag) { + cost = d.cost; + } else { + cost = 1; + } + to[d] = c, weight[d] = cost; + g[c].emplace_back(c, d, cost); + rc(rc, d, c); + } + }; + for (auto& r : g[N]) dfs(dfs, r, -1); + + calc_represent(N, -1); + } + + vector> get_loops() const { + vector> res; + for (auto r : g[N]) { + vector cur{r}; + for (int i = to[r]; i != r; i = to[i]) { + cur.push_back(i); + } + res.push_back(cur); + } + return res; + } + + // (u, {weight of u-v}) (v, {weight of v-w}), (w, ...) ... + vector>> get_loops_with_weight() const { + vector>> res; + for (auto r : g[N]) { + vector> cur{make_pair(r, weight[r])}; + for (int i = to[r]; i != r; i = to[i]) { + cur.emplace_back(i, weight[i]); + } + res.push_back(cur); + } + return res; + } + + private: + void calc_represent(int c, int r) { + represent[c] = r; + for (auto& d : g[c]) calc_represent(d, r == -1 ? d : r); + } +}; + +} // namespace FunctionalGraphImpl + +using FunctionalGraphImpl::FunctionalGraph; diff --git a/graph/funtional-graph.hpp b/graph/namori.hpp similarity index 100% rename from graph/funtional-graph.hpp rename to graph/namori.hpp diff --git a/math/affine-transformation.hpp b/math/affine-transformation.hpp index c9271b102..aaf67ce9d 100644 --- a/math/affine-transformation.hpp +++ b/math/affine-transformation.hpp @@ -5,11 +5,12 @@ struct Affine { mint a, b; constexpr Affine() : a(1), b(0) {} constexpr Affine(mint _a, mint _b) : a(_a), b(_b) {} - mint operator()(mint x) const { return a * x + b; } // R(L(x)) friend Affine operator*(const Affine& l, const Affine& r) { return Affine(l.a * r.a, l.b * r.a + r.b); } + mint operator()(mint x) const { return a * x + b; } + Affine operator()(const Affine& r) const { return r * (*this); } bool operator==(const Affine& r) const { return a == r.a && b == r.b; } bool operator!=(const Affine& r) const { return a != r.a || b != r.b; } friend ostream& operator<<(ostream& os, const Affine& r) { diff --git a/matrix/gauss-elimination.hpp b/matrix/gauss-elimination.hpp index 0ea230e65..b84b0db7a 100644 --- a/matrix/gauss-elimination.hpp +++ b/matrix/gauss-elimination.hpp @@ -11,6 +11,7 @@ using namespace std; template std::pair GaussElimination(vector> &a, int pivot_end = -1, bool diagonalize = false) { + if (a.empty()) return {0, 1}; int H = a.size(), W = a[0].size(), rank = 0; if (pivot_end == -1) pivot_end = W; T det = 1; diff --git a/ntt/multiplicative-convolution-mod-p.hpp b/ntt/multiplicative-convolution-mod-p.hpp new file mode 100644 index 000000000..26fe44bef --- /dev/null +++ b/ntt/multiplicative-convolution-mod-p.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +using namespace std; + +#include "../math/constexpr-primitive-root.hpp" + +template +fps multiplicative_convolution_mod_p(const fps& a, const fps& b, int p) { + assert((int)a.size() == p); + assert((int)b.size() == p); + using mint = typename fps::value_type; + int r = constexpr_primitive_root(p); + vector exp(p - 1), log(p); + exp[0] = 1; + for (int i = 1; i < p - 1; i++) exp[i] = 1LL * exp[i - 1] * r % p; + for (int i = 0; i < p - 1; i++) log[exp[i]] = i; + fps s(p - 1), t(p - 1); + for (int i = 0; i < p - 1; i++) s[i] = a[exp[i]], t[i] = b[exp[i]]; + fps u = s * t; + for (int i = p - 1; i < (int)u.size(); i++) u[i % (p - 1)] += u[i]; + fps c(p); + for (int i = 1; i < p; i++) c[i] = u[log[i]]; + + mint sa = accumulate(begin(a), end(a), mint{}); + mint sb = accumulate(begin(b), end(b), mint{}); + c[0] = sa * b[0] + sb * a[0] - a[0] * b[0]; + return c; +} diff --git a/tree/static-top-tree-vertex-based.hpp b/tree/static-top-tree-vertex-based.hpp index 9d54f7f89..c2f70fecc 100644 --- a/tree/static-top-tree-vertex-based.hpp +++ b/tree/static-top-tree-vertex-based.hpp @@ -167,19 +167,19 @@ using StaticTopTreeVertexBasedImpl::StaticTopTreeVertexBased; // template using Path = ; using Point = ; - auto vertex = [&](int) -> Path { + auto vertex = [&](int i) -> Path { }; auto compress = [&](const Path& p, const Path& c) -> Path { }; - auto rake = [&](const Point& l, const Point& r) -> Point { + auto rake = [&](const Point& a, const Point& b) -> Point { }; - auto add_edge = [&](const Path& d) -> Point { + auto add_edge = [&](const Path& a) -> Point { }; - auto add_vertex = [&](const Point& d, int) -> Path { + auto add_vertex = [&](const Point& a, int i) -> Path { }; HeavyLightDecomposition hld{g}; diff --git a/verify/verify-aoj-other/aoj-2891-2.test.cpp b/verify/verify-aoj-other/aoj-2891-2.test.cpp new file mode 100644 index 000000000..b9cb565ca --- /dev/null +++ b/verify/verify-aoj-other/aoj-2891-2.test.cpp @@ -0,0 +1,33 @@ +#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2891" +// +#include "../../template/template.hpp" +// +#include "../../data-structure/union-find.hpp" +#include "../../graph/functional-graph.hpp" +#include "../../graph/graph-template.hpp" + +using namespace Nyaan; + +void q() { + ini(N); + auto g = graph(N, N); + FunctionalGraph fg{N, g}; + UnionFind uf(N); + auto loops = fg.get_loops(); + each(loop, loops) { + int x = loop[0]; + each(y, loop) uf.unite(x, y); + } + ini(Q); + while (Q--) { + ini(a, b); + --a, --b; + out(uf.same(a, b) ? 2 : 1); + } +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-aoj-other/aoj-2891.test.cpp b/verify/verify-aoj-other/aoj-2891.test.cpp index 5eaab7489..59a6c5223 100644 --- a/verify/verify-aoj-other/aoj-2891.test.cpp +++ b/verify/verify-aoj-other/aoj-2891.test.cpp @@ -2,7 +2,7 @@ // #include "../../template/template.hpp" // -#include "../../graph/funtional-graph.hpp" +#include "../../graph/namori.hpp" using namespace Nyaan; diff --git a/verify/verify-yosupo-ds/yosupo-range-set-range-composite.test.cpp b/verify/verify-yosupo-ds/yosupo-range-set-range-composite.test.cpp new file mode 100644 index 000000000..786f2347d --- /dev/null +++ b/verify/verify-yosupo-ds/yosupo-range-set-range-composite.test.cpp @@ -0,0 +1,56 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/range_set_range_composite" +// +#include "../../template/template.hpp" +// +#include "../../math/affine-transformation.hpp" +#include "../../segment-tree/lazy-segment-tree.hpp" +// +#include "../../modint/montgomery-modint.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; + +using namespace Nyaan; + +void q() { + ini(N, Q); + + using A = Affine; + using D = pair; + + D ti = make_pair(A{1, 0}, 0); + A ei{0, 0}; + auto f = [](const D& a, const D& b) -> D { + return make_pair(b.fi(a.fi), a.se + b.se); + }; + auto g = [](const D& a, const A& b) -> D { + return make_pair(Power(b, a.se, A{1, 0}), a.se); + }; + auto h = [](const A&, const A& b) { return b; }; + + V v(N, make_pair(ei, 1)); + rep(i, N) in(v[i].fi.a, v[i].fi.b); + + LazySegmentTree seg(v, f, g, h, ti, ei); + + rep(i, Q) { + ini(cmd); + if (cmd == 0) { + ini(l, r, c, d); + seg.update(l, r, A{c, d}); + } else { + ini(l, r, x); + auto a = seg.query(l, r); + out(a.fi(x)); + } + } +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-ds/yosupo-static-rectangle-add-rectangle-sum.test.cpp b/verify/verify-yosupo-ds/yosupo-static-rectangle-add-rectangle-sum.test.cpp new file mode 100644 index 000000000..f77e09f22 --- /dev/null +++ b/verify/verify-yosupo-ds/yosupo-static-rectangle-add-rectangle-sum.test.cpp @@ -0,0 +1,36 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/static_rectangle_add_rectangle_sum" +// +#include "../../template/template.hpp" +// +#include "../../data-structure-2d/rectangle-add-rectangle-sum.hpp" +// +#include "../../modint/montgomery-modint.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; + +using namespace Nyaan; + +void q() { + inl(N, Q); + RectangleAddRectangleSum rr; + rep(i, N) { + ini(l, d, r, u, w); + rr.add_rectangle(l, r, d, u, w); + } + rep(i, Q) { + ini(l, d, r, u); + rr.add_query(l, r, d, u); + } + auto ans = rr.solve(); + each(x, ans) out(x); +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root-2.test.cpp b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root-2.test.cpp new file mode 100644 index 000000000..31ffa2b2b --- /dev/null +++ b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root-2.test.cpp @@ -0,0 +1,69 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/point_set_tree_path_composite_sum_fixed_root" +// +#include "../../template/template.hpp" +// +#include "../../modint/montgomery-modint.hpp" +// +#include "../../tree/dynamic-rerooting.hpp" +// +using mint = LazyMontgomeryModInt<998244353>; + +struct Path { + mint a, b, s, x; +}; +struct Point { + mint s, x; +}; +struct Info { + bool vertex; + mint x, y; +}; +Path vertex(const Info &i) { + if (i.vertex) return {1, 0, i.x, 1}; + return {i.x, i.y, 0, 0}; +} +Path compress(const Path &p, const Path &c) { + return {p.a * c.a, p.a * c.b + p.b, p.s + p.a * c.s + p.b * c.x, p.x + c.x}; +} +Point rake(const Point &a, const Point &b) { return {a.s + b.s, a.x + b.x}; } +Point add_edge(const Path &a) { return {a.s, a.x}; } +Path add_vertex(const Point &a, const Info &i) { + if (i.vertex) return {1, 0, a.s + i.x, a.x + 1}; + return {i.x, i.y, a.s * i.x + a.x * i.y, a.x}; +} + +using DR = DynamicRerooting; + +using namespace Nyaan; + +void Nyaan::solve() { + int N, Q; + in(N, Q); + vector A(N); + for (auto &x : A) in(x); + vector U(N - 1), V(N - 1), B(N - 1), C(N - 1); + for (int i = 0; i < N - 1; i++) in(U[i], V[i], B[i], C[i]); + + vector info(2 * N - 1); + for (int i = 0; i < N; i++) info[i] = {true, A[i], 0}; + for (int i = 0; i < N - 1; i++) info[N + i] = {false, B[i], C[i]}; + + DR dr{2 * N - 1, info}; + for (int i = 0; i < N - 1; i++) { + dr.add_edge(N + i, U[i]), dr.add_edge(N + i, V[i]); + } + + while (Q--) { + int cmd, i, x; + in(cmd, i, x); + if (cmd == 0) { + dr.set_info(i, {true, x, 0}); + } else { + int y; + in(y); + dr.set_info(N + i, {false, x, y}); + } + out(dr.query(0).s.get()); + } +} diff --git a/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root.test.cpp b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root.test.cpp new file mode 100644 index 000000000..dafc65802 --- /dev/null +++ b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum-fixed-root.test.cpp @@ -0,0 +1,77 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/point_set_tree_path_composite_sum_fixed_root" +// +#include "../../template/template.hpp" +// +#include "../../modint/montgomery-modint.hpp" +// +#include "../../tree/static-top-tree-vertex-based.hpp" +// +using mint = LazyMontgomeryModInt<998244353>; + +struct Path { + mint a, b, s, x; +}; +struct Point { + mint s, x; +}; +vector calc(int N, int Q, vector A, vector U, vector V, + vector B, vector C, vector cmd, vector I, + vector X, vector Y) { + vector> g(2 * N - 1); + rep(e, N - 1) { + g[N + e].push_back(U[e]), g[U[e]].push_back(N + e); + g[N + e].push_back(V[e]), g[V[e]].push_back(N + e); + } + auto vertex = [&](int i) -> Path { + if (i < N) return {1, 0, A[i], 1}; + int e = i - N; + return {B[e], C[e], 0, 0}; + }; + auto compress = [&](const Path& p, const Path& c) -> Path { + return {p.a * c.a, p.a * c.b + p.b, p.s + p.a * c.s + p.b * c.x, p.x + c.x}; + }; + auto rake = [&](const Point& a, const Point& b) -> Point { + return {a.s + b.s, a.x + b.x}; + }; + auto add_edge = [&](const Path& a) -> Point { return {a.s, a.x}; }; + auto add_vertex = [&](const Point& a, int i) -> Path { + if (i < N) return {1, 0, a.s + A[i], a.x + 1}; + int e = i - N; + return {B[e], C[e], a.s * B[e] + a.x * C[e], a.x}; + }; + + HeavyLightDecomposition hld{g}; + DPonStaticTopTreeVertexBased< + vector>, Path, Point, decltype(vertex), decltype(compress), + decltype(rake), decltype(add_edge), decltype(add_vertex)> + dp(hld, vertex, compress, rake, add_edge, add_vertex); + + vector ans(Q); + rep(q, Q) { + if (cmd[q] == 0) { + A[I[q]] = X[q]; + dp.update(I[q]); + } else { + B[I[q]] = X[q], C[I[q]] = Y[q]; + dp.update(N + I[q]); + } + ans[q] = dp.get().s; + } + return ans; +} + +void Nyaan::solve() { + int N, Q; + in(N, Q); + vector A(N); + for (auto& x : A) in(x); + vector U(N - 1), V(N - 1), B(N - 1), C(N - 1); + rep(i, N - 1) in(U[i], V[i], B[i], C[i]); + vector cmd(Q), I(Q), X(Q), Y(Q, -1); + rep(i, Q) { + in(cmd[i], I[i], X[i]); + if (cmd[i] == 1) in(Y[i]); + } + auto ac = calc(N, Q, A, U, V, B, C, cmd, I, X, Y); + for (auto& x : ac) out(x.get()); +} diff --git a/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum.test.cpp b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum.test.cpp new file mode 100644 index 000000000..76094efd8 --- /dev/null +++ b/verify/verify-yosupo-graph/yosupo-point-set-tree-path-composite-sum.test.cpp @@ -0,0 +1,70 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/point_set_tree_path_composite_sum" +// +#include "../../template/template.hpp" +// +#include "../../modint/montgomery-modint.hpp" +// +#include "../../tree/dynamic-rerooting.hpp" +// +using mint = LazyMontgomeryModInt<998244353>; + +struct Path { + mint a, b, s, x; +}; +struct Point { + mint s, x; +}; +struct Info { + bool vertex; + mint x, y; +}; +Path vertex(const Info &i) { + if (i.vertex) return {1, 0, i.x, 1}; + return {i.x, i.y, 0, 0}; +} +Path compress(const Path &p, const Path &c) { + return {p.a * c.a, p.a * c.b + p.b, p.s + p.a * c.s + p.b * c.x, p.x + c.x}; +} +Point rake(const Point &a, const Point &b) { return {a.s + b.s, a.x + b.x}; } +Point add_edge(const Path &a) { return {a.s, a.x}; } +Path add_vertex(const Point &a, const Info &i) { + if (i.vertex) return {1, 0, a.s + i.x, a.x + 1}; + return {i.x, i.y, a.s * i.x + a.x * i.y, a.x}; +} + +using DR = DynamicRerooting; + +using namespace Nyaan; + +void Nyaan::solve() { + int N, Q; + in(N, Q); + vector A(N); + for (auto &x : A) in(x); + vector U(N - 1), V(N - 1), B(N - 1), C(N - 1); + for (int i = 0; i < N - 1; i++) in(U[i], V[i], B[i], C[i]); + + vector info(2 * N - 1); + for (int i = 0; i < N; i++) info[i] = {true, A[i], 0}; + for (int i = 0; i < N - 1; i++) info[N + i] = {false, B[i], C[i]}; + + DR dr{2 * N - 1, info}; + for (int i = 0; i < N - 1; i++) { + dr.add_edge(N + i, U[i]), dr.add_edge(N + i, V[i]); + } + + while (Q--) { + int cmd, i, x; + in(cmd, i, x); + if (cmd == 0) { + dr.set_info(i, {true, x, 0}); + } else { + int y; + in(y); + dr.set_info(N + i, {false, x, y}); + } + ini(r); + out(dr.query(r).s.get()); + } +} diff --git a/verify/verify-yosupo-math/yosupo-pow-of-matrix-2.test.cpp b/verify/verify-yosupo-math/yosupo-pow-of-matrix-2.test.cpp new file mode 100644 index 000000000..56b74559f --- /dev/null +++ b/verify/verify-yosupo-math/yosupo-pow-of-matrix-2.test.cpp @@ -0,0 +1,31 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_matrix" +// +#include "../../template/template.hpp" +// +#include "../../matrix/matrix-fast.hpp" +// +#include "../../modint/montgomery-modint.hpp" +#include "../../modulo/binomial.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; +Binomial C; + +using namespace Nyaan; + +void q() { + inl(N, K); + Matrix m; + rep(i, N) rep(j, N) in(m[i][j]); + m = m ^ K; + rep(i, N) rep(j, N) cout << m[i][j] << " \n"[j + 1 == N]; +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-math/yosupo-pow-of-matrix.test.cpp b/verify/verify-yosupo-math/yosupo-pow-of-matrix.test.cpp new file mode 100644 index 000000000..6ba67dd63 --- /dev/null +++ b/verify/verify-yosupo-math/yosupo-pow-of-matrix.test.cpp @@ -0,0 +1,31 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_matrix" +// +#include "../../template/template.hpp" +// +#include "../../matrix/matrix.hpp" +// +#include "../../modint/montgomery-modint.hpp" +#include "../../modulo/binomial.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; +Binomial C; + +using namespace Nyaan; + +void q() { + inl(N, K); + Matrix m(N); + rep(i, N) rep(j, N) in(m[i][j]); + m = m ^ K; + rep(i, N) out(m[i]); +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-math/yosupo-rank-of-matrix.test.cpp b/verify/verify-yosupo-math/yosupo-rank-of-matrix.test.cpp new file mode 100644 index 000000000..06c315857 --- /dev/null +++ b/verify/verify-yosupo-math/yosupo-rank-of-matrix.test.cpp @@ -0,0 +1,36 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/matrix_rank" +// +#include "../../template/template.hpp" +// +#include "../../matrix/gauss-elimination.hpp" +// +#include "../../modint/montgomery-modint.hpp" +#include "../../modulo/binomial.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; +Binomial C; + +using namespace Nyaan; + +void q() { + ini(N, M); + vvm m(N, vm(M)); + in(m); + if (N > M) { + vvm m2(M, vm(N)); + rep(i, N) rep(j, M) m2[j][i] = m[i][j]; + m = m2; + } + int rank = GaussElimination(m).fi; + out(rank); +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-math/yosupo-rational-approximation.test.cpp b/verify/verify-yosupo-math/yosupo-rational-approximation.test.cpp new file mode 100644 index 000000000..f5e5ecbe3 --- /dev/null +++ b/verify/verify-yosupo-math/yosupo-rational-approximation.test.cpp @@ -0,0 +1,26 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/rational_approximation" +// +#include "../../template/template.hpp" +// +#include "../../math/stern-brocot-tree-binary-search.hpp" +using namespace Nyaan; + +void q() { + ini(N, x, y); + ll z = gcd(x, y); + x /= z, y /= z; + if (max(x, y) <= N) die(x, y, x, y); + auto [lo, up] = binary_search_on_stern_brocot_tree( + [&](pair ab) { + auto [a, b] = ab; + return a * y >= b * x; + }, + N); + die(lo.fi, lo.se, up.fi, up.se); +} + +void Nyaan::solve() { + int t = 1; + in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-ntt/yosupo-convolution-on-z-pz.test.cpp b/verify/verify-yosupo-ntt/yosupo-convolution-on-z-pz.test.cpp new file mode 100644 index 000000000..c1643e735 --- /dev/null +++ b/verify/verify-yosupo-ntt/yosupo-convolution-on-z-pz.test.cpp @@ -0,0 +1,30 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/mul_modp_convolution" +// +#include "../../template/template.hpp" +// +#include "../../ntt/multiplicative-convolution-mod-p.hpp" +// +#include "../../fps/ntt-friendly-fps.hpp" +#include "../../modint/montgomery-modint.hpp" +// +using namespace Nyaan; +using mint = LazyMontgomeryModInt<998244353>; +// using mint = LazyMontgomeryModInt<1000000007>; +using vm = vector; +using vvm = vector; +using fps = FormalPowerSeries; + +using namespace Nyaan; + +void q() { + ini(p); + fps a(p), b(p); + in(a, b); + out(multiplicative_convolution_mod_p(a, b, p)); +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-other/yosupo-static-convex-hull-2.test.cpp b/verify/verify-yosupo-other/yosupo-static-convex-hull-2.test.cpp new file mode 100644 index 000000000..568c8ec8e --- /dev/null +++ b/verify/verify-yosupo-other/yosupo-static-convex-hull-2.test.cpp @@ -0,0 +1,21 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/static_convex_hull" +// +#include "../../template/template.hpp" +// +#include "../../geometry/integer-geometry.hpp" +using namespace Nyaan; + +void q() { + ini(N); + V ps(N); + in(ps); + auto cv = ConvexHull(ps); + out(sz(cv)); + each2(x, y, cv) out(x, y); +} + +void Nyaan::solve() { + int t = 1; + in(t); + while (t--) q(); +} diff --git a/verify/verify-yosupo-other/yosupo-static-convex-hull.test.cpp b/verify/verify-yosupo-other/yosupo-static-convex-hull.test.cpp new file mode 100644 index 000000000..fdb2f47c6 --- /dev/null +++ b/verify/verify-yosupo-other/yosupo-static-convex-hull.test.cpp @@ -0,0 +1,21 @@ +#define PROBLEM "https://judge.yosupo.jp/problem/static_convex_hull" +// +#include "../../template/template.hpp" +// +#include "../../geometry/polygon.hpp" +using namespace Nyaan; + +void q() { + ini(N); + V ps(N); + in(ps); + auto cv = convex_hull(ps); + out(sz(cv)); + each2(x, y, cv) out(ll(x), ll(y)); +} + +void Nyaan::solve() { + int t = 1; + in(t); + while (t--) q(); +} diff --git a/verify/verify-yuki/yuki-1254-2.test.cpp b/verify/verify-yuki/yuki-1254-2.test.cpp new file mode 100644 index 000000000..12e86ae1c --- /dev/null +++ b/verify/verify-yuki/yuki-1254-2.test.cpp @@ -0,0 +1,46 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1254" +// +#include "../../template/template.hpp" +// +#include "../../graph/functional-graph.hpp" +#include "../../graph/graph-template.hpp" + +using namespace Nyaan; + +void q() { + ini(N); + WeightedGraph g(N); + map, int> es; + + rep1(i, N) { + ini(u, v); + --u, --v; + es[minmax(u, v)] = i; + g[u].emplace_back(u, v, i); + g[v].emplace_back(v, u, i); + } + + FunctionalGraph fg{N, g}; + auto loops = fg.get_loops_with_weight(); + assert(sz(loops) == 1); + + auto loop = loops[0]; + trc(loop); + vi ans; + rep(i, sz(loop)) { + int u = loop[i].fi; + int v = loop[(i + 1) % sz(loop)].fi; + + if (es[minmax(u, v)] != loop[i].se) exit(1); + ans.push_back(loop[i].se); + } + sort(all(ans)); + out(sz(ans)); + out(ans); +} + +void Nyaan::solve() { + int t = 1; + // in(t); + while (t--) q(); +} diff --git a/verify/verify-yuki/yuki-1254.test.cpp b/verify/verify-yuki/yuki-1254.test.cpp index 52bd90330..3f86aa719 100644 --- a/verify/verify-yuki/yuki-1254.test.cpp +++ b/verify/verify-yuki/yuki-1254.test.cpp @@ -2,7 +2,7 @@ // #include "../../template/template.hpp" // -#include "../../graph/funtional-graph.hpp" +#include "../../graph/namori.hpp" using namespace Nyaan;