diff --git a/.github/workflows/document.yml b/.github/workflows/document.yml index a2f9b23..eae3cb9 100644 --- a/.github/workflows/document.yml +++ b/.github/workflows/document.yml @@ -31,13 +31,13 @@ jobs: VERSION: ${{ steps.version.outputs.VERSION_NAME }} - name: Publish to github pages if: ${{ github.event_name == 'push' }} - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: - deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./tools/generated destination_dir: ${{ steps.version.outputs.VERSION_NAME }} - name: Upload zip - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ac-library path: tools/ac-library.zip \ No newline at end of file diff --git a/.github/workflows/expander.yml b/.github/workflows/expander.yml index 1f7049c..3fef573 100644 --- a/.github/workflows/expander.yml +++ b/.github/workflows/expander.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/atcoder/convolution.hpp b/atcoder/convolution.hpp index d206205..de3f1ae 100644 --- a/atcoder/convolution.hpp +++ b/atcoder/convolution.hpp @@ -130,7 +130,7 @@ void butterfly_inv(std::vector& a) { auto r = a[i + offset + p]; a[i + offset] = l + r; a[i + offset + p] = - (unsigned long long)(mint::mod() + l.val() - r.val()) * + (unsigned long long)((unsigned int)(l.val() - r.val()) + mint::mod()) * irot.val(); ; } @@ -223,8 +223,8 @@ std::vector convolution(std::vector&& a, std::vector&& b) { int z = (int)internal::bit_ceil((unsigned int)(n + m - 1)); assert((mint::mod() - 1) % z == 0); - if (std::min(n, m) <= 60) return convolution_naive(a, b); - return internal::convolution_fft(a, b); + if (std::min(n, m) <= 60) return convolution_naive(std::move(a), std::move(b)); + return internal::convolution_fft(std::move(a), std::move(b)); } template * = nullptr> std::vector convolution(const std::vector& a, diff --git a/atcoder/dsu.hpp b/atcoder/dsu.hpp index 4bc453f..5776da6 100644 --- a/atcoder/dsu.hpp +++ b/atcoder/dsu.hpp @@ -35,8 +35,7 @@ struct dsu { int leader(int a) { assert(0 <= a && a < _n); - if (parent_or_size[a] < 0) return a; - return parent_or_size[a] = leader(parent_or_size[a]); + return _leader(a); } int size(int a) { @@ -69,6 +68,11 @@ struct dsu { // root node: -1 * component size // otherwise: parent std::vector parent_or_size; + + int _leader(int a) { + if (parent_or_size[a] < 0) return a; + return parent_or_size[a] = _leader(parent_or_size[a]); + } }; } // namespace atcoder diff --git a/atcoder/lazysegtree.hpp b/atcoder/lazysegtree.hpp index c858663..9a5a5cf 100644 --- a/atcoder/lazysegtree.hpp +++ b/atcoder/lazysegtree.hpp @@ -26,10 +26,10 @@ struct lazy_segtree { "e must work as S()"); static_assert( std::is_convertible_v>, - "mapping must work as F(F, S)"); + "mapping must work as S(F, S)"); static_assert( std::is_convertible_v>, - "compostiion must work as F(F, F)"); + "composition must work as F(F, F)"); static_assert(std::is_convertible_v>, "id must work as F()"); diff --git a/atcoder/modint.hpp b/atcoder/modint.hpp index cfcf815..44f968b 100644 --- a/atcoder/modint.hpp +++ b/atcoder/modint.hpp @@ -48,7 +48,7 @@ struct static_modint : internal::static_modint_base { _v = (unsigned int)(v % umod()); } - unsigned int val() const { return _v; } + int val() const { return _v; } mint& operator++() { _v++; @@ -165,7 +165,7 @@ template struct dynamic_modint : internal::modint_base { _v = (unsigned int)(v % mod()); } - unsigned int val() const { return _v; } + int val() const { return _v; } mint& operator++() { _v++; diff --git a/atcoder/string.hpp b/atcoder/string.hpp index 2c68258..5da8963 100644 --- a/atcoder/string.hpp +++ b/atcoder/string.hpp @@ -213,10 +213,12 @@ std::vector suffix_array(const std::string& s) { template std::vector lcp_array(const std::vector& s, const std::vector& sa) { + assert(s.size() == sa.size()); int n = int(s.size()); assert(n >= 1); std::vector rnk(n); for (int i = 0; i < n; i++) { + assert(0 <= sa[i] && sa[i] < n); rnk[sa[i]] = i; } std::vector lcp(n - 1); diff --git a/document_en/fenwicktree.md b/document_en/fenwicktree.md index 7539bfa..306353b 100644 --- a/document_en/fenwicktree.md +++ b/document_en/fenwicktree.md @@ -1,6 +1,6 @@ # Fenwick Tree -Given an array of length $N$, it processes the following queries in $O(\log N)$ time. +Given an array of length $n$, it processes the following queries in $O(\log n)$ time. - Updating an element - Calculating the sum of the elements of an interval diff --git a/document_en/lazysegtree.md b/document_en/lazysegtree.md index 2f7738e..8d7f43c 100644 --- a/document_en/lazysegtree.md +++ b/document_en/lazysegtree.md @@ -126,7 +126,7 @@ It returns `op(a[0], ..., a[n - 1])`, assuming the properties of the monoid. It ```cpp (1) int seg.max_right(int l) -(2 ) int seg.max_right(int l, G g) +(2💻) int seg.max_right(int l, G g) ``` - (1): It applies a binary search on the segment tree. The function `bool g(S x)` should be defined. @@ -153,7 +153,7 @@ If `g` is monotone, this is the maximum `r` that satisfies `g(op(a[l], a[l + 1], ```cpp (1) int seg.min_left(int r) -(2 ) int seg.min_left(int r, G g) +(2💻) int seg.min_left(int r, G g) ``` - (1): It applies a binary search on the segment tree. The function `bool g(S x)` should be defined. diff --git a/document_en/mincostflow.md b/document_en/mincostflow.md index 95bb20e..49be78a 100644 --- a/document_en/mincostflow.md +++ b/document_en/mincostflow.md @@ -66,7 +66,7 @@ Let $g$ be a function such that $g(x)$ is the cost of the minimum cost $s-t$ flo It returns $g$ as the list of the changepoints, that satisfies the followings. - The first element of the list is $(0, 0)$. -- Both of `.first` and `.second` are strictly increasing. +- `.first` is strictly increasing and `.second` is non-decreasing. - No three changepoints are on the same line. - (1) The last element of the list is $(x, g(x))$, where $x$ is the maximum amount of the $s-t$ flow. - (2) The last element of the list is $(y, g(y))$, where $y = \min(x, \mathrm{flow\\_limit})$. diff --git a/document_en/segtree.md b/document_en/segtree.md index d9b8020..3a200cd 100644 --- a/document_en/segtree.md +++ b/document_en/segtree.md @@ -5,7 +5,7 @@ It is the data structure for [monoids](https://en.wikipedia.org/wiki/Monoid) $(S - associativity: $(a \cdot b) \cdot c$ = $a \cdot (b \cdot c)$ for all $a, b, c \in S$ - existence of the identity element: $a \cdot e$ = $e \cdot a$ = $a$ for all $a \in S$ -Given an array $S$ of length $N$, it processes the following queries in $O(\log N)$ time (see [Appendix](./appendix.html) for further details). +Given an array $S$ of length $n$, it processes the following queries in $O(\log n)$ time (see [Appendix](./appendix.html) for further details). - Updating an element - Calculating the product of the elements of an interval diff --git a/document_ja/fenwicktree.md b/document_ja/fenwicktree.md index 9206b59..251edb2 100644 --- a/document_ja/fenwicktree.md +++ b/document_ja/fenwicktree.md @@ -1,11 +1,11 @@ # Fenwick Tree -長さ $N$ の配列に対し、 +長さ $n$ の配列に対し、 - 要素の $1$ 点変更 - 区間の要素の総和 -を $O(\log N)$ で求めることが出来るデータ構造です。 +を $O(\log n)$ で求めることが出来るデータ構造です。 ## コンストラクタ diff --git a/document_ja/mincostflow.md b/document_ja/mincostflow.md index 0428b77..42aac65 100644 --- a/document_ja/mincostflow.md +++ b/document_ja/mincostflow.md @@ -66,7 +66,7 @@ vector> graph.slope(int s, int t, Cap flow_limit); 返り値に流量とコストの関係の折れ線が入る。全ての $x$ について、流量 $x$ の時の最小コストを $g(x)$ とすると、$(x, g(x))$ は返り値を折れ線として見たものに含まれる。 - 返り値の最初の要素は $(0, 0)$ -- 返り値の`.first`、`.second`は共に狭義単調増加 +- 返り値の`.first` は狭義単調増加、`.second`は広義単調増加 - 3点が同一線上にあることはない - (1) 返り値の最後の要素は最大流量 $x$ として $(x, g(x))$ - (2) 返り値の最後の要素は $y = \min(x, \mathrm{flow\\_limit})$ として $(y, g(y))$ diff --git a/document_ja/segtree.md b/document_ja/segtree.md index e989100..f1fdde7 100644 --- a/document_ja/segtree.md +++ b/document_ja/segtree.md @@ -7,12 +7,12 @@ を満たす代数構造に対し使用できるデータ構造です。 -長さ $N$ の $S$ の配列に対し、 +長さ $n$ の $S$ の配列に対し、 - 要素の $1$ 点変更 - 区間の要素の総積の取得 -を $O(\log N)$ で行うことが出来ます。詳細な要件は [Appendix](./appendix.html) を参照してください。 +を $O(\log n)$ で行うことが出来ます。詳細な要件は [Appendix](./appendix.html) を参照してください。 また、このライブラリはオラクルとして`op, e`の2種類を使用しますが、これらが定数時間で動くものと仮定したときの計算量を記述します。オラクル内部の計算量が $O(f(n))$ である場合はすべての計算量が $O(f(n))$ 倍となります。 diff --git a/expander.py b/expander.py index ff773da..e4b87f3 100755 --- a/expander.py +++ b/expander.py @@ -63,14 +63,18 @@ def expand_acl(self, acl_file_path: Path) -> List[str]: result.append(line) return result - def expand(self, source: str) -> str: + def expand(self, source: str, origname) -> str: self.included = set() result = [] # type: List[str] + linenum = 0 for line in source.splitlines(): + linenum += 1 m = self.atcoder_include.match(line) if m: acl_path = self.find_acl(m.group(1)) result.extend(self.expand_acl(acl_path)) + if origname: + result.append('#line ' + str(linenum + 1) + ' "' + origname + '"') continue result.append(line) @@ -88,6 +92,8 @@ def expand(self, source: str) -> str: parser.add_argument('-c', '--console', action='store_true', help='Print to Console') parser.add_argument('--lib', help='Path to Atcoder Library') + parser.add_argument('--origname', help='report line numbers from the original ' + + 'source file in GCC/Clang error messages') opts = parser.parse_args() lib_paths = [] @@ -99,7 +105,7 @@ def expand(self, source: str) -> str: lib_paths.append(Path.cwd()) expander = Expander(lib_paths) source = open(opts.source).read() - output = expander.expand(source) + output = expander.expand(source, opts.origname) if opts.console: print(output)