Skip to content

Commit

Permalink
Merge pull request #108 from NyaanNyaan/add_misc
Browse files Browse the repository at this point in the history
add misc
  • Loading branch information
NyaanNyaan authored May 3, 2024
2 parents 248eb71 + d7e6b9e commit 915a6bd
Show file tree
Hide file tree
Showing 27 changed files with 922 additions and 61 deletions.
108 changes: 61 additions & 47 deletions .verify-helper/timestamps.remote.json

Large diffs are not rendered by default.

17 changes: 15 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
90 changes: 90 additions & 0 deletions data-structure-2d/rectangle-add-rectangle-sum.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include <vector>
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 I, class T>
class RectangleAddRectangleSum {
struct AddQuery {
I xl, xr, yl, yr;
T val;
};
struct SumQuery {
I xl, xr, yl, yr;
};
vector<AddQuery> add_queries;
vector<SumQuery> 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<T> solve() const {
vector<I> 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<tuple<I, int, int>> 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<T> b00(Y), b01(Y), b10(Y), b11(Y);
vector<T> 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;
}
};
7 changes: 4 additions & 3 deletions geometry/integer-geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions geometry/polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ Real area(const Polygon &p) {
// boundary : 周上の点も列挙する場合 true
template <bool boundary = false>
Polygon convex_hull(vector<Point> 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<Point> ch(2 * n);
// 反時計周り
Real th = boundary ? -EPS : +EPS;
Expand Down
127 changes: 127 additions & 0 deletions graph/functional-graph.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#pragma once

#include <cassert>
#include <utility>
#include <vector>
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 <typename T = int>
struct FunctionalGraph {
int N;
WeightedGraph<T> g;
vector<int> to, represent;
vector<T> weight;

FunctionalGraph() = default;

FunctionalGraph(int n, const vector<int>& adj,
const vector<T>& w = vector<int>{})
: 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 <typename G>
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<typename G::value_type::value_type>;
WeightedGraph<T> 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<vector<int>> get_loops() const {
vector<vector<int>> res;
for (auto r : g[N]) {
vector<int> 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<vector<pair<int, T>>> get_loops_with_weight() const {
vector<vector<pair<int, T>>> res;
for (auto r : g[N]) {
vector<pair<int, T>> 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;
File renamed without changes.
3 changes: 2 additions & 1 deletion math/affine-transformation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions matrix/gauss-elimination.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using namespace std;
template <typename T>
std::pair<int, T> GaussElimination(vector<vector<T>> &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;
Expand Down
30 changes: 30 additions & 0 deletions ntt/multiplicative-convolution-mod-p.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <cassert>
#include <vector>
using namespace std;

#include "../math/constexpr-primitive-root.hpp"

template <typename fps>
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<int> 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;
}
8 changes: 4 additions & 4 deletions tree/static-top-tree-vertex-based.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
33 changes: 33 additions & 0 deletions verify/verify-aoj-other/aoj-2891-2.test.cpp
Original file line number Diff line number Diff line change
@@ -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();
}
2 changes: 1 addition & 1 deletion verify/verify-aoj-other/aoj-2891.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
#include "../../template/template.hpp"
//
#include "../../graph/funtional-graph.hpp"
#include "../../graph/namori.hpp"

using namespace Nyaan;

Expand Down
Loading

0 comments on commit 915a6bd

Please sign in to comment.