ATCODER_
で始まる名前のマクロを使わないでください。__int128 / unsigned __int128(g++, clang++)
か _mul128 / _umul128(Visual Studio)
が使えること__builtin_(ctz/ctzll/clz/clzll/popcount)(g++, clang++)
か _BitScan(Forward/Reverse)(Visual Studio)
が使えることchar / short / int / ll
が 8 / 16 / 32 / 64
bit、またそのunsigned
型(およびsigned char
)も同じbit長一番わかりやすい方法は、トップページに書いたように、main.cpp
と同じ場所にatcoder
フォルダを置いて、g++ main.cpp -std=c++14 -I .
と実行することです。ここで、.
はフォルダを表す記号です(本当に I の後にスペース、点、と入力します。)
atcoder
フォルダをいちいちコピーしたくない場合は以下のような方法があります。
g++ main.cpp -std=c++14 -I /path/to/ac-library
のように指定する (/path/to/ac-library
は自分のPCの ac-library
を置いてある場所へ書き換えてください)。CPLUS_INCLUDE_PATH
で、CPLUS_INCLUDE_PATH="/path/to/ac-library"
のようにatcoder
フォルダの場所を指定する。(Windowsの場合は、ユーザー環境変数の設定画面 で、変数の欄に CPLUS_INCLUDE_PATH
値の欄に C:\path\to\ac-library
などと入力する。スラッシュではなくバックスラッシュを用いることに注意。なお、バックスラッシュは環境によっては円記号として表示されることがあります)。すると普通にg++ main.cpp -std=c++14
とコンパイルできる。古いVisual Studioを使っている場合、アップデートしてください。Visual Studio 2017 / 2019をサポートしています。
Visual Studioがインストールされているならば、以下のようなフォルダがあるはずです。
C:\Program Files (x86)\Microsoft Visual Studio\2019\(Community, Professional or Enterprise)\VC\Tools\MSVC\(Some number, e.g. 14.27.29110)\include
C:\Program Files (x86)\Microsoft Visual Studio\2017\(Community, Professional or Enterprise)\VC\Tools\MSVC\(Some number, e.g. 14.10.25017)\include
このなかに丸ごと atcoder
フォルダをコピーしてください。つまり、
C:\Program Files (x86)\Microsoft Visual Studio\2019\(Community, Professional or Enterprise)\VC\Tools\MSVC\(Some number, e.g. 14.27.29110)\include\atcoder\dsu.hpp
となるように配置してください。
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
という文字列をint
やstring
のように扱えばよいです。例えば
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$) となります。
modint
以外の構造体のコンストラクタには explicit が付いています。
Segtree / LazySegtree を使いたい状況において、扱う代数構造が無限集合である場合があります。たとえば、与えられた区間の $\mathrm{max}$ を求める、与えられた区間内の全ての要素に定数を足す、の二種類のクエリに対応する LazySegtree はよくありますが、このときたとえば $S = \mathrm{int}$ としてしまうと、$S$ は加法について閉じていない (overflow を起こす可能性がある) ため、厳密な意味でドキュメント本編の制約を満たしません。そこで、AC Library では以下のような場合正しく動くことを保証しています。
たとえば、最初の例で自然に $(S, F)$ を定めると以下のようになりますが、これは無限集合です。
$(S', F')$ を以下のように定めることで、制約が十分小さければこのライブラリで扱うことができます。
内部では各辺 $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
へ変更します。