diff --git a/document_ja/appendix.html b/document_ja/appendix.html deleted file mode 100644 index a30116e..0000000 --- a/document_ja/appendix.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Appendix / FAQ

-

動作環境

- -

インストール方法

-

g++ / clang++へのインストール方法

-

一番わかりやすい方法は、トップページに書いたように、main.cppと同じ場所にatcoderフォルダを置いて、g++ main.cpp -std=c++14 -I .と実行することです。ここで、.はフォルダを表す記号です(本当に I の後にスペース、点、と入力します。)

-

atcoderフォルダをいちいちコピーしたくない場合は以下のような方法があります。

- -

Visual Studioへのインストール方法

-

古いVisual Studioを使っている場合、アップデートしてください。Visual Studio 2017 / 2019をサポートしています。

-

Visual Studioがインストールされているならば、以下のようなフォルダがあるはずです。

- -

このなかに丸ごと atcoder フォルダをコピーしてください。つまり、

- -

となるように配置してください。

-

他のジャッジへの提出方法

-

expander.pyというスクリプト(python3.5 or later)を用意しています。 -python3 expander.py main.cppと実行するとcombined.cppが生成され、これは他のオンラインジャッジに提出できる形になっています。

-

テストはしていますが、サポート保証外です。

-

ドキュメントの表記法 / 明記されていないこと

-

💻マーク

-

C++初心者には難しいかもしれない機能を表すマークです。AC Libraryは、このマークの付いた箇所を無視してもアルゴリズム的に困らないように設計されています。modintなどが該当します。

-

テンプレート関数

-

例えばsuffix_array(v)vector<int>, vector<ll>などを引数に取れるのですが、これらをまとめてsuffix_array<T>(vector<T> v)と表記します。

-

例えばvector<int>に格納された整数列 $v$ の suffix array を求めたいとき、

-
vector<int> sa = suffix_array(v);
-// vector<int> sa = suffix_array<int>(v); ではないことに注意
-
- -

と使います。

-

デフォルトコンストラクタ

-

構造体、例えばscc_graph などは、サンプルのように

-
#include <atcoder/scc>;
-using namespace atcoder;
-
-int main() {
-    int n;
-    scanf("%d", &n);
-    scc_graph g(n); // n 頂点からなるグラフを生成
-    return 0;
-}
-
- -

といった宣言方法だけでなく、次のように初期化なしで宣言することも出来ます。

-
#include <atcoder/scc>;
-using namespace atcoder;
-
-scc_graph g;
-
-int main() {
-    return 0;
-}
-
- -

このように宣言したときの挙動(デフォルトコンストラクタ)は、

- -

となります。また、構造体に後から代入することも出来ます。

-
#include <atcoder/scc>;
-using namespace atcoder;
-
-scc_graph g;
-
-int main() {
-    g = scc_graph(10);
-    return 0;
-}
-
- -

辺の型

-

最大流ライブラリなどでは、辺の型として mf_graph<Cap>::edge というのを使います。

-

例えば、mf_graph<int> の辺の型は mf_graph<int>::edge です。 -:: が見慣れないかもしれないですが、mf_graph<int>::edge という文字列をintstringのように扱えばよいです。例えば

-
vector<mf_graph<int>::edge> v;
-mf_graph<int>::edge e;
-
- -

のようになります。

-

デフォルトテンプレート引数

-

convolution のように、以下のような表記法を用いることがあります。

-
vector<T> convolution<int m = 998244353>(vector<T> a, vector<T> b)
-
- -

これは、二通りの使い方ができることを表します。

-
vector<long long> c = convolution(a, b);
-vector<long long> c = convolution<924844033>(a, b);
-
- -

上段のように使った場合は、$m$ の値は自動的に $998244353$ となります。 -下段のように使った場合は、$m$ の値は明示的に与えた値 (この場合は $924844033$) となります。

-

Segtree / LazySegtree の厳密な要件

-

Segtree / LazySegtree を使いたい状況において、扱う代数構造が無限集合である場合があります。たとえば、与えられた区間の $\mathrm{max}$ を求める、与えられた区間内の全ての要素に定数を足す、の二種類のクエリに対応する LazySegtree はよくありますが、このときたとえば $S = \mathrm{int}$ としてしまうと、$S$ は加法について閉じていない (overflow を起こす可能性がある) ため、厳密な意味でドキュメント本編の制約を満たしません。そこで、AC Library では以下のような場合正しく動くことを保証しています。

-

Segtree

- -

LazySegtree

- -

たとえば、最初の例で自然に $(S, F)$ を定めると以下のようになりますが、これは無限集合です。

- -

$(S', F')$ を以下のように定めることで、制約が十分小さければこのライブラリで扱うことができます。

- -

maxflowの挙動

-

内部では各辺 $e$ について $2$ つの変数、流量 $f_e$ と容量 $c_e$ を管理しています。頂点 $v$ から出る辺の集合を $\mathrm{out}(v)$, 入る辺の集合を$\mathrm{in}(v)$ 、また頂点 $v$ について $g(v, f) = \sum_{e \in \mathrm{in}(v)}{f_e} - \sum_{e \in \mathrm{out}(v)}{f_e}$ とします。

-

flow(s, t)

-

これを呼ぶと各辺の流量を変更します。厳密には変更前と変更後の流量を $f_e$, $f'_e$ として、以下の条件を満たすように変更します。

- -

min_cut(s)

-

各辺 $e = (u, v, f_e, c_e)$について、$f_e \lt c_e$ ならば辺 $(u, v)$ を張り、$0 \lt f_e$ ならば辺 $(v, u)$ を張ったと仮定したとき、頂点 $s$ から到達可能な頂点の集合を返します。

-

change_edge(i, new_cap, new_flow)

-

辺 $i$ の流量、容量のみを new_flow, new_cap へ変更します。

-
-
- - - diff --git a/document_ja/convolution.html b/document_ja/convolution.html deleted file mode 100644 index 8c08d3a..0000000 --- a/document_ja/convolution.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Convolution

-

畳み込みを行います。数列 $a_0, a_1, \cdots, a_{N - 1}$ と数列 $b_0, b_1, \cdots, b_{M - 1}$ から、長さ $N + M - 1$ の数列

-

$$c_i = \sum_{j = 0}^i a_j b_{i - j}$$

-

を計算します。

-

convolution

-
(1) vector<T> convolution<int m = 998244353>(vector<T> a, vector<T> b)
-💻(2) vector<static_modint<m>> convolution<int m>(vector<static_modint<m>> a, vector<static_modint<m>> b)
-
- -

畳み込みを $\bmod m$ で計算します。$a, b$ の少なくとも一方が空配列の場合は空配列を返します。

-

制約

- -

計算量

-

$n = |a| + |b|$ として

- -

convolution_ll

-
vector<ll> convolution_ll(vector<ll> a, vector<ll> b)
-
- -

畳み込みを計算します。$a, b$ の少なくとも一方が空配列の場合は空配列を返します。

-

制約

- -

計算量

-

$n = |a| + |b|$ として

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_f

-
#include <atcoder/convolution> -#include <atcoder/modint> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -int main() { - int n, m; - scanf("%d %d", &n, &m); - vector<long long> a(n), b(m); - for (int i = 0; i < n; i++) { - scanf("%lld", &(a[i])); - } - for (int i = 0; i < m; i++) { - scanf("%lld", &(b[i])); - } - - vector<long long> c = convolution(a, b); - // or: vector<long long> c = convolution<998244353>(a, b); - - for (int i = 0; i < n + m - 1; i++) { - printf("%lld ", c[i]); - } - printf("\n"); - - return 0; -} -
- -

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_f

-
#include <atcoder/convolution> -#include <atcoder/modint> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -using mint = modint998244353; - -int main() { - int n, m; - scanf("%d %d", &n, &m); - vector<mint> a(n), b(m); - for (int i = 0; i < n; i++) { - int x; - scanf("%d", &x); - a[i] = x; - } - for (int i = 0; i < m; i++) { - int x; - scanf("%d", &x); - b[i] = x; - } - - auto c = convolution(a, b); - - for (int i = 0; i < n + m - 1; i++) { - printf("%d ", c[i].val()); - } - printf("\n"); - - return 0; -} -
-
-
- - - diff --git a/document_ja/dsu.html b/document_ja/dsu.html deleted file mode 100644 index 6d65f23..0000000 --- a/document_ja/dsu.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

DSU

-

無向グラフに対して、

- -

をならし $O(\alpha(n))$ 時間で処理することが出来ます。

-

また、内部的に各連結成分ごとに代表となる頂点を $1$ つ持っています。辺の追加により連結成分がマージされる時、新たな代表元は元の連結成分の代表元のうちどちらかになります。

-

コンストラクタ

-
dsu d(int n)
-
- - -

制約

- -

計算量

- -

merge

-
int d.merge(int a, int b)
-
- -

辺 $(a, b)$ を足します。

-

$a, b$ が連結だった場合はその代表元、非連結だった場合は新たな代表元を返します。

-

制約

- -

計算量

- -

same

-
bool d.same(int a, int b)
-
- -

頂点 $a, b$ が連結かどうかを返します。

-

制約

- -

計算量

- -

leader

-
int d.leader(int a)
-
- -

頂点 $a$ の属する連結成分の代表元を返します。

-

制約

- -

計算量

- -

size

-
int d.size(int a)
-
- -

頂点 $a$ の属する連結成分のサイズを返します。

-

制約

- -

計算量

- -

groups

-
vector<vector<int>> d.groups()
-
- -

グラフを連結成分に分け、その情報を返します。

-

返り値は「「一つの連結成分の頂点番号のリスト」のリスト」です。 -(内側外側限らず)vector内でどの順番で頂点が格納されているかは未定義です。

-

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_a

-
#include <atcoder/dsu> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -int main() { - int n, q; - scanf("%d %d", &n, &q); - dsu d(n); - for (int i = 0; i < q; i++) { - int t, u, v; - scanf("%d %d %d", &t, &u, &v); - if (t == 0) { - d.merge(u, v); - } else { - if (d.same(u, v)) { - printf("1\n"); - } else { - printf("0\n"); - } - } - } - return 0; -} -
-
-
- - - diff --git a/document_ja/fenwicktree.html b/document_ja/fenwicktree.html deleted file mode 100644 index 27d39da..0000000 --- a/document_ja/fenwicktree.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Fenwick Tree

-

長さ $N$ の配列に対し、

- -

を $O(\log N)$ で求めることが出来るデータ構造です。

-

コンストラクタ

-
fenwick_tree<T> fw(int n)
-
- - -

制約

- -

計算量

- -

add

-
void fw.add(int p, T x)
-
- -

a[p] += x を行う

-

制約

- -

計算量

- -

sum

-
T fw.sum(int l, int r)
-
- -

a[l] + a[l + 1] + ... + a[r - 1] を返す。 -T が整数型(int / uint / ll / ull)の場合、答えがオーバーフローしたならば $\bmod 2^{\mathrm{bit}}$ で等しい値が返る。

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_b

-
#include <atcoder/fenwicktree> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -int main() { - int n, q; - scanf("%d %d", &n, &q); - - fenwick_tree<long long> fw(n); - for (int i = 0; i < n; i++) { - int a; - scanf("%d", &a); - fw.add(i, a); - } - - for (int i = 0; i < q; i++) { - int t; - scanf("%d", &t); - if (t == 0) { - int p, x; - scanf("%d %d", &p, &x); - fw.add(p, x); - } else { - int l, r; - scanf("%d %d", &l, &r); - printf("%lld\n", fw.sum(l, r)); - } - } -} -
-
-
- - - diff --git a/document_ja/index.html b/document_ja/index.html deleted file mode 100644 index 211d5bf..0000000 --- a/document_ja/index.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

AC(AtCoder) Library Document

-

インストール方法

- -

お約束

- -

リスト

-

#include <atcoder/all> : 一括include

-

データ構造

- -

数学

- -

グラフ

- -

付録

- -

テスト

- -

ライセンス

-

ヘッダファイル群(同梱の atcoder フォルダ以下)はCC0ライセンスで公開しています。詳しくはatcoder/LICENSEを参照してください。

-
-
- - - diff --git a/document_ja/keywords.toml b/document_ja/keywords.toml deleted file mode 100644 index a8abf1a..0000000 --- a/document_ja/keywords.toml +++ /dev/null @@ -1,3 +0,0 @@ -constraints = '制約' -complexity = '計算量' -examples = '使用例' diff --git a/document_ja/lazysegtree.html b/document_ja/lazysegtree.html deleted file mode 100644 index efee9f6..0000000 --- a/document_ja/lazysegtree.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Lazy Segtree

-

モノイド $(S, \cdot: S \times S \to S, e \in S)$と、$S$ から $S$ への写像の集合 $F$ であって、以下の条件を満たすようなものについて使用できるデータ構造です。

- -

長さ $N$ の $S$ の配列に対し、

- -

を $O(\log N)$ で行うことが出来ます。詳細な要件は Appendix を参照してください。

-

また、このライブラリはオラクルとしてop, e, mapping, composition, idを使用しますが、これらが定数時間で動くものと仮定したときの計算量を記述します。オラクル内部の計算量が $O(f(n))$ である場合はすべての計算量が $O(f(n))$ 倍となります。

-

コンストラクタ

-
(1) lazy_segtree<S, op, e, F, mapping, composition, id> seg(int n);
-(2) lazy_segtree<S, op, e, F, mapping, composition, id> seg(vector<T> v);
-
- - -

を定義する必要があります。 -詳しくは、使用例や こちら も参照してください。

- -

制約

- -

計算量

- -

set

-
void seg.set(int p, S x)
-
- -

a[p] = x

-

制約

- -

計算量

- -

get

-
S seg.get(int p)
-
- -

a[p] を返します。

-

制約

- -

計算量

- -

prod

-
S seg.prod(int l, int r)
-
- -

op(a[l], ..., a[r - 1]) を、モノイドの性質を満たしていると仮定して計算します。$l = r$ のときは e() を返します。

-

制約

- -

計算量

- -

all_prod

-
S seg.all_prod()
-
- -

op(a[0], ..., a[n-1]) を計算します。$n = 0$ のときは e() を返します。

-

計算量

- -

apply

-
(1) void seg.apply(int p, F f)
-(2) void seg.apply(int l, int r, F f)
-
- - -

制約

- -

計算量

- -

max_right

-
(1) int seg.max_right<g>(int l)
-(2💻) int seg.max_right<G>(int l, G g)
-
- - -

以下の条件を両方満たす r を(いずれか一つ)返します。

- -

gが単調だとすれば、g(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最大の r、と解釈することが可能です。

-

制約

- -

計算量

- -

min_left

-
(1) int seg.min_left<g>(int r)
-(2💻) int seg.min_left<G>(int r, G g)
-
- - -

以下の条件を両方満たす l を(いずれか一つ)返します。

- -

gが単調だとすれば、g(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最小の l、と解釈することが可能です。

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_k

-
#include <atcoder/lazysegtree> -#include <atcoder/modint> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -using mint = modint998244353; - -struct S { - mint a; - int size; -}; - -struct F { - mint a, b; -}; - -S op(S l, S r) { return S{l.a + r.a, l.size + r.size}; } - -S e() { return S{0, 0}; } - -S mapping(F l, S r) { return S{r.a * l.a + r.size * l.b, r.size}; } - -F composition(F l, F r) { return F{r.a * l.a, r.b * l.a + l.b}; } - -F id() { return F{1, 0}; } - -int main() { - int n, q; - scanf("%d %d", &n, &q); - - vector<S> a(n); - for (int i = 0; i < n; i++) { - int x; - scanf("%d", &x); - a[i] = S{x, 1}; - } - - lazy_segtree<S, op, e, F, mapping, composition, id> seg(a); - - for (int i = 0; i < q; i++) { - int t; - scanf("%d", &t); - if (t == 0) { - int l, r; - int c, d; - scanf("%d %d %d %d", &l, &r, &c, &d); - seg.apply(l, r, F{c, d}); - } else { - int l, r; - scanf("%d %d", &l, &r); - printf("%d\n", seg.prod(l, r).a.val()); - } - } -} -
- -

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_l

-
#include <atcoder/lazysegtree> -#include <atcoder/modint> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -using mint = modint998244353; - -struct S { - // # of 0 / # of 1 / inversion number - long long zero, one, inversion; -}; - -// swapping flag -using F = bool; - -S op(S l, S r) { - return S{ - l.zero + r.zero, - l.one + r.one, - l.inversion + r.inversion + l.one * r.zero, - }; -} - -S e() { return S{0, 0, 0}; } - -S mapping(F l, S r) { - if (!l) return r; - // swap - return S{r.one, r.zero, r.one * r.zero - r.inversion}; -} - -F composition(F l, F r) { return (l && !r) || (!l && r); } - -F id() { return false; } - -int main() { - int n, q; - scanf("%d %d", &n, &q); - - vector<S> a(n); - for (int i = 0; i < n; i++) { - int x; - scanf("%d", &x); - if (x == 0) - a[i] = S{1, 0, 0}; - else - a[i] = S{0, 1, 0}; - } - - lazy_segtree<S, op, e, F, mapping, composition, id> seg(a); - for (int i = 0; i < q; i++) { - int t, l, r; - scanf("%d %d %d", &t, &l, &r); - l--; - if (t == 1) { - seg.apply(l, r, true); - } else { - printf("%lld\n", seg.prod(l, r).inversion); - } - } -} -
-
-
- - - diff --git a/document_ja/math.html b/document_ja/math.html deleted file mode 100644 index 41efa24..0000000 --- a/document_ja/math.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Math

-

数論的アルゴリズム詰め合わせです。

-

pow_mod

-
ll pow_mod(ll x, ll n, int m)
-
- -

$x^n \bmod m$ を返します。

-

制約

- -

計算量

- -

inv_mod

-
ll inv_mod(ll x, ll m)
-
- -

$xy \equiv 1 \pmod m$ なる $y$ のうち、$0 \le y < m$ を満たすものを返します。

-

制約

- -

計算量

- -

crt

-
pair<ll, ll> crt(vector<ll> r, vector<ll> m)
-
- -

同じ長さの配列 $r, m$ を渡します。この配列の長さを $n$ とした時、

-

$$x \equiv r[i] \pmod{m[i]}, \forall i \in \lbrace 0,1,\cdots, n - 1 \rbrace$$

-

を解きます。答えは(存在するならば) $y, z (0 \leq y < z = \mathrm{lcm}(m[i]))$ を用いて $x \equiv y \pmod z$ の形で書けることが知られており、この $(y, z)$ をpairとして返します。答えがない場合は $(0, 0)$ を返します。$n=0$ の時は $(0, 1)$ を返します。

-

制約

- -

計算量

- -

floor_sum

-
ll floor_sum(ll n, ll m, ll a, ll b)
-
- -

$\sum_{i = 0}^{n - 1} \mathrm{floor}(\frac{a \times i + b}{m})$

-

を返します。

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_c

-
#include <atcoder/math> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -int main() { - int t; - scanf("%d", &t); - for (int i = 0; i < t; i++) { - long long n, m, a, b; - scanf("%lld %lld %lld %lld", &n, &m, &a, &b); - printf("%lld\n", floor_sum(n, m, a, b)); - } - return 0; -} -
-
-
- - - diff --git a/document_ja/maxflow.html b/document_ja/maxflow.html deleted file mode 100644 index 5c188cf..0000000 --- a/document_ja/maxflow.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

MaxFlow

-

最大フロー問題 を解くライブラリです。

-

コンストラクタ

-
mf_graph<Cap> graph(int n)
-
- -

n 頂点 $0$ 辺のグラフを作る。Capは容量の型。

-

制約

- -

計算量

- -

add_edge

-
int graph.add_edge(int from, int to, Cap cap);
-
- -

fromからtoへ最大容量cap、流量 $0$ の辺を追加し、何番目に追加された辺かを返す。

-

制約

- -

計算量

- -

flow

-
(1) Cap graph.flow(int s, int t);
-(2) Cap graph.flow(int s, int t, Cap flow_limit);
-
- - -

制約

- -

計算量

-

$m$ を追加された辺数として

- -

min_cut

-
vector<bool> graph.min_cut(int s)
-
- -

長さ $n$ のvectorを返す。$i$ 番目の要素には、頂点 $s$ から $i$ へ残余グラフで到達可能なとき、またその時のみ true を返す。flow(s, t)をflow_limitなしでちょうど一回呼んだ後に呼ぶと、返り値は $s$, $t$ 間のmincutに対応します。詳細な挙動は Appendix を参照してください。

-

計算量

-

$m$ を追加された辺数として

- -

get_edge / edges

-
struct mf_graph<Cap>::edge {
-    int from, to;
-    Cap cap, flow;
-};
-
-(1) mf_graph<Cap>::edge graph.get_edge(int i);
-(2) vector<mf_graph<Cap>::edge> graph.edges();
-
- - -

制約

-

計算量

-

$m$ を追加された辺数として

- -

change_edge

-
void graph.change_edge(int i, Cap new_cap, Cap new_flow);
-
- -

$i$ 番目に変更された辺の容量、流量をnew_cap, new_flowに変更する。他の辺の容量、流量は変更しない。詳細は Appendix を参照してください

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_d

-
#include <atcoder/maxflow> -#include <iostream> - -using namespace std; -using namespace atcoder; - -int main() { - int n, m; - cin >> n >> m; - - vector<string> grid(n); - for (int i = 0; i < n; i++) { - cin >> grid[i]; - } - - /** - * generate (s -> even grid -> odd grid -> t) graph - * grid(i, j) correspond to vertex (i * m + j) - **/ - mf_graph<int> g(n * m + 2); - int s = n * m, t = n * m + 1; - - // s -> even / odd -> t - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (grid[i][j] == '#') continue; - int v = i * m + j; - if ((i + j) % 2 == 0) { - g.add_edge(s, v, 1); - } else { - g.add_edge(v, t, 1); - } - } - } - - // even -> odd - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if ((i + j) % 2 || grid[i][j] == '#') continue; - int v0 = i * m + j; - if (i && grid[i - 1][j] == '.') { - int v1 = (i - 1) * m + j; - g.add_edge(v0, v1, 1); - } - if (j && grid[i][j - 1] == '.') { - int v1 = i * m + (j - 1); - g.add_edge(v0, v1, 1); - } - if (i + 1 < n && grid[i + 1][j] == '.') { - int v1 = (i + 1) * m + j; - g.add_edge(v0, v1, 1); - } - if (j + 1 < m && grid[i][j + 1] == '.') { - int v1 = i * m + (j + 1); - g.add_edge(v0, v1, 1); - } - } - } - - cout << g.flow(s, t) << endl; - - auto edges = g.edges(); - for (auto e : edges) { - if (e.from == s || e.to == t || e.flow == 0) continue; - int i0 = e.from / m, j0 = e.from % m; - int i1 = e.to / m, j1 = e.to % m; - - if (i0 == i1 + 1) { - grid[i1][j1] = 'v'; - grid[i0][j0] = '^'; - } else if (j0 == j1 + 1) { - grid[i1][j1] = '>'; grid[i0][j0] = '<'; - } else if (i0 == i1 - 1) { - grid[i0][j0] = 'v'; - grid[i1][j1] = '^'; - } else { - grid[i0][j0] = '>'; grid[i1][j1] = '<'; - } - } - - for (int i = 0; i < n; i++) { - cout << grid[i] << endl; - } - - return 0; -} -
-
-
- - - diff --git a/document_ja/mincostflow.html b/document_ja/mincostflow.html deleted file mode 100644 index f31d2bd..0000000 --- a/document_ja/mincostflow.html +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

MinCostFlow

-

Minimum-cost flow problemを扱うライブラリです。

-

コンストラクタ

-
mcf_graph<Cap, Cost> graph(int n);
-
- -

$n$ 頂点 $0$ 辺のグラフを作る。Capは容量の型、Costはコストの型

-

制約

- -

計算量

- -

add_edge

-
int graph.add_edge(int from, int to, Cap cap, Cost cost);
-
- -

fromからtoへ最大容量cap, コストcostの辺を追加する。何番目に追加された辺かを返す。

-

制約

- -

計算量

- -

min_cost_max_flow

-
(1) pair<Cap, Cost> graph.flow(int s, int t);
-(2) pair<Cap, Cost> graph.flow(int s, int t, Cap flow_limit);
-
- -

$s$ から $t$ へ流せるだけ流し、その流量とコストを返す。

- -

制約

- -

計算量

- -

min_cost_slope

-
vector<pair<Cap, Cost>> graph.slope(int s, int t);
-vector<pair<Cap, Cost>> graph.slope(int s, int t, Cap flow_limit);
-
- -

帰り値に流量とコストの関係の折れ線が入る。全ての $x$ について、流量 $x$ の時の最小コストを $g(x)$ とすると、$(x, g(x))$ は帰り値を折れ線として見たものに含まれる。

- -

制約

-

辺のコストの最大を $x$ として

- -

計算量

-

$F$を流量、$m$を追加した辺の本数として

- -

edges

-
struct edge<Cap, Cost> {
-    int from, to;
-    Cap cap, flow;
-    Cost cost;
-};
-
-(1) mcf_graph<Cap, Cost>::edge graph.get_edge(int i);
-(2) vector<mcf_graph<Cap, Cost>::edge> graph.edges();
-
- - -

$m$ を追加された辺数として

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_e

-
#include <atcoder/mincostflow> -#include <iostream> - -using namespace std; -using namespace atcoder; - -const long long BIG = 1'000'000'000; - -int main() { - int n, k; - cin >> n >> k; - - /** - * generate (s -> row -> column -> t) graph - * i-th row correspond to vertex i - * i-th col correspond to vertex n + i - **/ - mcf_graph<int, long long> g(2 * n + 2); - int s = 2 * n, t = 2 * n + 1; - - // we can "waste" the flow - g.add_edge(s, t, n * k, BIG); - - for (int i = 0; i < n; i++) { - g.add_edge(s, i, k, 0); - g.add_edge(n + i, t, k, 0); - } - - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - long long a; - cin >> a; - g.add_edge(i, n + j, 1, BIG - a); - } - } - - auto result = g.flow(s, t, n * k); - cout << 1LL * n * k * BIG - result.second << endl; - - vector<string> grid(n, string(n, '.')); - auto edges = g.edges(); - for (auto e : edges) { - if (e.from == s || e.to == t || e.flow == 0) continue; - - grid[e.from][e.to - n] = 'X'; - } - - for (int i = 0; i < n; i++) { - cout << grid[i] << endl; - } - return 0; -} -
-
-
- - - diff --git a/document_ja/modint.html b/document_ja/modint.html deleted file mode 100644 index 5ea1f75..0000000 --- a/document_ja/modint.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Modint

-

自動でmodを取る構造体です。AC Libraryはmodintを使わなくとも全アルゴリズムが使えるように整備しているので、必ずしもこのファイルの内容を把握する必要はありません。

-

多くの問題では modint998244353, modint1000000007, modint のどれかを使えば十分で、以下のように使えます。

-
#include <atcoder/modint>
-#include <iostream>
-
-using namespace std;
-using namespace atcoder;
-
-using mint = modint998244353;
-// or: typedef modint998244353 mint;
-
-int main() {
-    // print sum of array (mod 998244353)
-    int n;
-    cin >> n;
-    mint sum = 0;
-    for (int i = 0; i < n; i++) {
-        int x;
-        cin >> x;
-        sum += x;
-    }
-    cout << sum.val() << endl;
-}
-
- -

modがfixedでない場合は、modint を使用し以下のように書けます。

-
#include <atcoder/modint>
-#include <iostream>
-
-using namespace std;
-
-using mint = modint;
-// or: typedef modint mint;
-
-int main() {
-    // print sum of array (input mod)
-    int n, mod;
-    cin >> n >> mod;
-    mint::set_mod(mod);
-    mint sum = 0;
-    for (int i = 0; i < n; i++) {
-        int x;
-        cin >> x;
-        sum += x;
-    }
-    cout << sum.val() << endl;
-}
-
- -

以下の関数らは、set_mod を除き $3$ つともに対して動きます。

-

コンストラクタ

-
(1) modint x()
-(2) modint x<T>(T y)
-
- - -

set_mod

-
void modint::set_mod(int m)
-
- -

modを設定します。最初に呼んでください。

-

制約

- -

計算量

- -

mod

-
int modint::mod()
-
- -

modを返します。

-

val

-
int x.val();
-
- -

xに格納されている値を返します。

-

各種演算

-
-modint;
-
-modint++;
-modint--;
-++modint;
---modint;
-
-modint + modint;
-modint - modint;
-modint * modint;
-modint / modint;
-
-modint += modint;
-modint -= modint;
-modint *= modint;
-modint /= modint;
-
-modint == modint;
-modint != modint;
-
- -

が動きます。

-
modint x = 10;
-1 + x;
-
- -

も(modint(1) + xと自動で解釈されるので)動きます。

-
modint::set_mod(11);
-modint y = 10;
-int z = 1234;
-y * z;
-
- -

y * modint(z)と解釈され、動きます。

-

制約

- -

計算量

- -

pow

-
modint x.pow(ll n)
-
- -

$x^n$ を返します。

-

制約

- -

計算量

- -

inv

-
modint x.inv()
-
- -

$xy \equiv 1$ なる $y$ を返します。

-

制約

- -

計算量

- -

raw

-
modint modint::raw(int x)
-
- -

xに対してmodを取らずに、modint(x)を返す。

-

定数倍高速化のための関数です。

-

上で述べたように

-
modint a;
-int i;
-a += i;
-
- -

は、iがmod以上でも動きます。勝手にiに対してmodを取るためです。

-

ですが、たとえば以下のようなコードでは、iがmodを超えないことを保証できます。

-
int main() {
-    modint::set_mod(1000000007);
-    modint a = 1;
-    for (int i = 1; i < 100000; i++) {
-        a += i;
-    }
-}
-
- -

このような時に、

-
int main() {
-    modint::set_mod(1000000007);
-    modint a = 1;
-    for (int i = 1; i < 100000; i++) {
-        a += modint::raw(i);
-    }
-}
-
- -

と書くと、modの回数を減らすことが出来ます。

-

当然ながらmodint::raw(x)にmod以上の値を入れたときの挙動は未定義です。

-

制約

- -

Tips(other mod)

-

問題文で他のmod (例: 1000000009) が与えられる場合、以下のように書けます

-
using mint = static_modint<1000000009>;
-
- -

modint998244353, modint1000000007 は、static_modint<998244353>, static_modint<1000000007>のエイリアスになっています。

-
using modint998244353 = static_modint<998244353>;
-using modint1000000007 = static_modint<1000000007>;
-
- -

Tips(複数mod)

-

複数種類modを使用したい場合以下のようにできます

-
using mint0 = dynamic_modint<0>;
-using mint1 = dynamic_modint<1>;
-
- -

modintは、dynamic_modint<-1>のエイリアスになっています。

-
using modint = dynamic_modint<-1>;
-
- -

使用例

-

How to Use

-
#include <atcoder/modint> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -using mint = static_modint<11>; -int main() { - mint a = 10; - mint b(3); - - // equal - assert(a == 21); - assert(a == -1); - assert(-1 == a); - - // negative - assert(-b == 8); - - // plus - assert(a + b == 2); // (10 + 3) mod 11 - assert(1 + a == 0); - - // minus - assert(a - b == 7); // (10 - 3) mod 11 - assert(b - a == 4); - - // mul - assert(a * b == 8); // (10 * 3) mod 11 - - // inv - assert(b.inv() == 4); // (3 * 4) mod 11 == 1 - - // div - assert(a / b == 7); // (10 * 4) mod 11 - - // +=, -=, *=, /= - a += b; - assert(a == 2 && b == 3); - a -= b; - assert(a == 10 && b == 3); - a *= b; - assert(a == 8 && b == 3); - a /= b; - assert(a == 10 && b == 3); - - // pow - assert(mint(2).pow(4) == 5); // 16 mod 11 - - // print value - printf("%d\n", a.val()); // 10 - - // get mod - assert(mint::mod() == 11 && a.mod() == 11); - - // mint(x) と書くとmodを取る操作が発生します((x % mod + mod) % modをmodintに代入します) - // mint::raw(x) はxをmodを取らずに代入するので高速です(もちろんxが[0, mod)であることを利用者が保証しないといけません) - assert(mint::raw(3) == 3); -} -
-
-
- - - diff --git a/document_ja/scc.html b/document_ja/scc.html deleted file mode 100644 index ff59928..0000000 --- a/document_ja/scc.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

SCC

-

有向グラフを強連結成分分解します。

-

コンストラクタ

-
scc_graph graph(int n)
-
- -

$n$ 頂点 $0$ 辺の有向グラフを作る。

-

制約

- -

計算量

- -

add_edge

-
void graph.add_edge(int from, int to)
-
- -

頂点 from から頂点 to へ有向辺を足す。

-

制約

- -

計算量

- -

scc

-
vector<vector<int>> graph.scc()
-
- -

以下の条件を満たすような、「頂点のリスト」のリストを返します。

- -

計算量

-

追加した辺の本数を $m$ として

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_g

-
#include <atcoder/scc> -#include <cstdio> - -using namespace std; -using namespace atcoder; - -int main() { - int n, m; - scanf("%d %d", &n, &m); - - scc_graph g(n); - - for (int i = 0; i < m; i++) { - int u, v; - scanf("%d %d", &u, &v); - g.add_edge(u, v); - } - - auto scc = g.scc(); - - printf("%d\n", int(scc.size())); - for (auto v : scc) { - printf("%d", int(v.size())); - for (int x : v) { - printf(" %d", x); - } - printf("\n"); - } - - return 0; -} -
-
-
- - - diff --git a/document_ja/segtree.html b/document_ja/segtree.html deleted file mode 100644 index 619b9a4..0000000 --- a/document_ja/segtree.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

Segtree

-

モノイド $(S, \cdot: S \times S \to S, e \in S)$、つまり

- -

を満たす代数構造に対し使用できるデータ構造です。

-

長さ $N$ の $S$ の配列に対し、

- -

を $O(\log N)$ で行うことが出来ます。詳細な要件は Appendix を参照してください。

-

また、このライブラリはオラクルとしてop, eの2種類を使用しますが、これらが定数時間で動くものと仮定したときの計算量を記述します。オラクル内部の計算量が $O(f(n))$ である場合はすべての計算量が $O(f(n))$ 倍となります。

-

コンストラクタ

-
(1) segtree<S, op, e> seg(int n)
-(2) segtree<S, op, e> seg(vector<S> v)
-
- - -

を定義する必要があります。例として、Range Min Queryならば

-
int op(int a, int b) {
-    return min(a, b);
-}
-
-int e() {
-    return (int)(1e9);
-}
-
-segtree<int, op, e> seg(10);
-
- -

のようになります。

- -

詳しくは、使用例や こちら も参照してください。

-

制約

- -

計算量

- -

set

-
void seg.set(int p, S x)
-
- -

a[p]x を代入します。

-

制約

- -

計算量

- -

get

-
S seg.get(int p)
-
- -

a[p] を返します。

-

制約

- -

計算量

- -

prod

-
S seg.prod(int l, int r)
-
- -

op(a[l], ..., a[r - 1]) を、モノイドの性質を満たしていると仮定して計算します。$l = r$ のときは e() を返します。

-

制約

- -

計算量

- -

all_prod

-
S seg.all_prod()
-
- -

op(a[0], ..., a[n - 1]) を計算します。$n = 0$ のときは e() を返します。

-

計算量

- -

max_right

-
(1) int seg.max_right<f>(int l)
-(2💻) int seg.max_right<F>(int l, F f)
-
- - -

以下の条件を両方満たす r を(いずれか一つ)返します。

- -

fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最大の r、と解釈することが可能です。

-

制約

- -

計算量

- -

min_left

-
(1) int seg.min_left<f>(int r)
-(2💻) int seg.min_left<F>(int r, F f)
-
- - -

以下の条件を両方満たす l を(いずれか一つ)返します。

- -

fが単調だとすれば、f(op(a[l], a[l + 1], ..., a[r - 1])) = true となる最小の l、と解釈することが可能です。

-

制約

- -

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_j

-
#include <atcoder/segtree> -#include <cstdio> -#include <vector> - -using namespace std; -using namespace atcoder; - -int op(int a, int b) { return max(a, b); } - -int e() { return -1; } - -int target; - -bool f(int v) { return v < target; } - -int main() { - int n, q; - scanf("%d %d", &n, &q); - vector<int> a(n); - for (int i = 0; i < n; i++) { - scanf("%d", &(a[i])); - } - - segtree<int, op, e> seg(a); - - for (int i = 0; i < q; i++) { - int t; - scanf("%d", &t); - if (t == 1) { - int x, v; - scanf("%d %d", &x, &v); - x--; - seg.set(x, v); - } else if (t == 2) { - int l, r; - scanf("%d %d", &l, &r); - l--; - printf("%d\n", seg.prod(l, r)); - } else if (t == 3) { - int p; - scanf("%d %d", &p, &target); - p--; - printf("%d\n", seg.max_right<f>(p) + 1); - } - } -} -
-
-
- - - diff --git a/document_ja/string.html b/document_ja/string.html deleted file mode 100644 index b703244..0000000 --- a/document_ja/string.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

String

-

文字列アルゴリズム詰め合わせです。 -文字列に関する様々なアルゴリズムが入っています。

-

文字列 s の $a$ 番目から $b - 1$ 番目の要素のsubstringを、s[a..b)と表記します。

-

suffix_array

-
(1) vector<int> suffix_array(string s)
-(2) vector<int> suffix_array<T>(vector<T> s)
-(3) vector<int> suffix_array(vector<int> s, int upper)
-
- -

長さ $n$ の文字列 s のSuffix Arrayとして、長さ $n$ の vector を返す。 -Suffix Array sa は $(0, 1, \dots, n - 1)$ の順列であって、各 $i = 0,1, \cdots ,n-2$ について s[sa[i]..n) < s[sa[i+1]..n) を満たすもの。

-

制約

- -

計算量

- -

lcp_array

-
(1) vector<int> lcp_array(string s, vector<int> sa)
-(2) vector<int> lcp_array<T>(vector<T> s, vector<int> sa)
-
- -

長さ $n$ の文字列 s のLCP Arrayとして、長さ $n-1$ の配列を返す。$i$ 番目の要素は s[sa[i]..n), s[sa[i+1]..n) の LCP(Longest Common Prefix) の長さ。

-

制約

- -

計算量

- -

z_algorithm

-
(1) vector<int> z_algorithm(string s)
-(2) vector<int> z_algorithm<T>(vector<T> s)
-
- -

入力の長さを $n$ として、長さ $n$ の配列を返す。 -$i$ 番目の要素は s[0..n)s[i..n)のLCP(Longest Common Prefix)の長さ。

-

制約

- -

計算量

- -

使用例

-

How to Use

-
#include <atcoder/string> -#include <string> -#include <vector> - -using namespace std; -using namespace atcoder; - -int main() { - string s = "missisippi"; - - vector<int> sa = suffix_array(s); - - vector<string> answer = { - "i", - "ippi", - "isippi", - "issisippi", - "missisippi", - "pi", - "ppi", - "sippi", - "sisippi", - "ssisippi", - }; - - assert(sa.size() == answer.size()); - for (int i = 0; i < int(sa.size()); i++) { - assert(s.substr(sa[i]) == answer[i]); - } -} -
- -

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_i

-
#include <atcoder/string> -#include <iostream> -#include <string> -#include <vector> - -using namespace std; -using namespace atcoder; - -int main() { - static char buf[500'001]; - scanf("%s", buf); - string s = buf; - vector<int> sa = suffix_array(s); - long long answer = 1LL * s.size() * (s.size() + 1) / 2; - for (auto x : lcp_array(s, sa)) { - answer -= x; - } - printf("%lld\n", answer); - return 0; -} -
-
-
- - - diff --git a/document_ja/twosat.html b/document_ja/twosat.html deleted file mode 100644 index bc7de92..0000000 --- a/document_ja/twosat.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-

2-SAT

-

2-SATを解きます。 -変数 $x_0, x_1, \cdots, x_{N - 1}$ に関して、

- -

というクローズを足し、これをすべて満たす変数の割当があるかを解きます。

-

コンストラクタ

-
two_sat ts(int n)
-
- -

$n$ 変数の2-SATを作ります。

-

制約

- -

計算量

- -

add_clause

-
void ts.add_clause(int i, bool f, int j, bool g)
-
- -

$(x_i = f) \lor (x_j = g)$ というクローズを足します。

-

制約

- -

計算量

- -

satisfiable

-
bool ts.satisfiable()
-
- -

条件を足す割当が存在するかどうかを判定する。割当が存在するならばtrue、そうでないならfalseを返す。

-

制約

- -

計算量

-

足した制約の個数を $m$ として

- -

answer

-
vector<bool> ts.answer()
-
- -

最後に呼んだ satisfiable の、クローズを満たす割当を返す。satisfiable を呼ぶ前や、satisfiable で割当が存在しなかったときにこの関数を呼ぶと、中身が未定義の長さ $n$ の vectorを返す。

-

計算量

- -

使用例

-

AC code of https://atcoder.jp/contests/practice2/tasks/practice2_h

-
#include <atcoder/twosat> -#include <iostream> -#include <vector> - -using namespace std; -using namespace atcoder; - -int main() { - int n, d; - cin >> n >> d; - vector<int> x(n), y(n); - for (int i = 0; i < n; i++) { - cin >> x[i] >> y[i]; - } - - // ts[i] = (i-th flag is located on x[i]) - two_sat ts(n); - - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (abs(x[i] - x[j]) < d) { - // cannot use both of x[i] and x[j] - ts.add_clause(i, false, j, false); - } - if (abs(x[i] - y[j]) < d) { - ts.add_clause(i, false, j, true); - } - if (abs(y[i] - x[j]) < d) { - ts.add_clause(i, true, j, false); - } - if (abs(y[i] - y[j]) < d) { - ts.add_clause(i, true, j, true); - } - } - } - - if (!ts.satisfiable()) { - cout << "No" << endl; - return 0; - } - - cout << "Yes" << endl; - auto answer = ts.answer(); - for (int i = 0; i < n; i++) { - if (answer[i]) - cout << x[i] << endl; - else - cout << y[i] << endl; - } - - return 0; -} -
-
-
- - -