ac-library-rb 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/unittest.yml +16 -3
  3. data/.rubocop.yml +61 -45
  4. data/README.ja.md +36 -8
  5. data/README.md +7 -4
  6. data/Rakefile +7 -3
  7. data/ac-library-rb.gemspec +11 -4
  8. data/ac-library-rb_header.jpg +0 -0
  9. data/bin/console +1 -1
  10. data/document_en/dsu.md +1 -1
  11. data/document_en/fenwick_tree.md +2 -2
  12. data/document_en/lazy_segtree.md +4 -4
  13. data/document_en/math.md +3 -3
  14. data/document_en/max_flow.md +3 -3
  15. data/document_en/min_cost_flow.md +4 -4
  16. data/document_en/modint.md +4 -4
  17. data/document_en/scc.md +67 -0
  18. data/document_en/segtree.md +2 -2
  19. data/document_ja/dsu.md +1 -1
  20. data/document_ja/fenwick_tree.md +2 -2
  21. data/document_ja/lazy_segtree.md +2 -2
  22. data/document_ja/math.md +3 -3
  23. data/document_ja/max_flow.md +4 -7
  24. data/document_ja/min_cost_flow.md +5 -4
  25. data/document_ja/modint.md +4 -4
  26. data/document_ja/scc.md +9 -8
  27. data/document_ja/segtree.md +2 -2
  28. data/lib/ac-library-rb/version.rb +1 -1
  29. data/lib/convolution.rb +1 -1
  30. data/lib/dsu.rb +14 -1
  31. data/lib/fenwick_tree.rb +4 -0
  32. data/lib/lazy_segtree.rb +2 -6
  33. data/lib/max_flow.rb +27 -26
  34. data/lib/modint.rb +4 -4
  35. data/lib/priority_queue.rb +14 -0
  36. data/lib/scc.rb +1 -1
  37. data/lib/two_sat.rb +1 -1
  38. data/lib_lock/ac-library-rb/convolution.rb +1 -1
  39. data/lib_lock/ac-library-rb/dsu.rb +14 -1
  40. data/lib_lock/ac-library-rb/fenwick_tree.rb +4 -0
  41. data/lib_lock/ac-library-rb/lazy_segtree.rb +2 -6
  42. data/lib_lock/ac-library-rb/max_flow.rb +27 -26
  43. data/lib_lock/ac-library-rb/modint.rb +4 -4
  44. data/lib_lock/ac-library-rb/priority_queue.rb +14 -0
  45. data/lib_lock/ac-library-rb/scc.rb +1 -1
  46. data/lib_lock/ac-library-rb/two_sat.rb +1 -1
  47. metadata +39 -7
@@ -147,10 +147,10 @@ It returns an index l that satisfies both of the following.
147
147
 
148
148
  ## Verified
149
149
 
150
- - [ALPC: J \- Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
150
+ - [ALPC: J - Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
151
151
  - [AC Code(884ms) max_right](https://atcoder.jp/contests/practice2/submissions/23196480)
152
152
  - [AC Code(914ms) min_left](https://atcoder.jp/contests/practice2/submissions/23197311)
153
- - [F \- Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
153
+ - [F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
154
154
  - [AC Code(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): Segtree(xor)
155
155
  - [AC Code(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT) xor
156
156
 
data/document_ja/dsu.md CHANGED
@@ -131,7 +131,7 @@ d.groups
131
131
 
132
132
  ## Verified
133
133
 
134
- - [A \- Disjoint Set Union](https://atcoder.jp/contests/practice2/tasks/practice2_a)
134
+ - [A - Disjoint Set Union](https://atcoder.jp/contests/practice2/tasks/practice2_a)
135
135
 
136
136
  ## 参考リンク
137
137
 
@@ -69,9 +69,9 @@ fw._sum(pos)
69
69
 
70
70
  ## Verified
71
71
 
72
- - [AtCoder ALPC B \- Fenwick Tree](https://atcoder.jp/contests/practice2/tasks/practice2_b)
72
+ - [AtCoder ALPC B - Fenwick Tree](https://atcoder.jp/contests/practice2/tasks/practice2_b)
73
73
  [ACコード(17074108)]https://atcoder.jp/contests/practice2/submissions/17074108 (1272ms)
74
- - [F \- Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
74
+ - [F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
75
75
  FenwickTree(BIT)をxorに改造するだけでも解けます。
76
76
  [ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200)。FenwickTree(BIT)のxor改造版です。
77
77
 
@@ -138,8 +138,8 @@ LazySegtree上で、二分探索をします。
138
138
  - [AIZU ONLINE JUDGE DSL\_2\_I RSQ and RUQ](https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_I) ([旧DSL_2_I](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I))
139
139
 
140
140
  以下の問題は、Rubyでは実行時間が厳しくTLEになりACできてないです。
141
- - [ALPC: K \- Range Affine Range Sum](https://atcoder.jp/contests/practice2/tasks/practice2_k)
142
- - [ALPC: L \- Lazy Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_l)
141
+ - [ALPC: K - Range Affine Range Sum](https://atcoder.jp/contests/practice2/tasks/practice2_k)
142
+ - [ALPC: L - Lazy Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_l)
143
143
 
144
144
  下記は、ジャッジにだしてないが、サンプルに正解。`max_right`, `min_left`を使う問題。
145
145
  - [Quora Programming Challenge 2021: Skyscraper](https://jonathanirvin.gs/files/division2_3d16774b0423.pdf#page=5)
data/document_ja/math.md CHANGED
@@ -70,7 +70,7 @@ Chinese remainder theorem
70
70
  ### Verified
71
71
 
72
72
  問題
73
- - [No\.187 中華風 \(Hard\) \- yukicoder](https://yukicoder.me/problems/no/187)
73
+ - [No\.187 中華風 \(Hard\) - yukicoder](https://yukicoder.me/problems/no/187)
74
74
 
75
75
  ## floor_sum(n, m, a, b)
76
76
 
@@ -86,7 +86,7 @@ $\sum_{i = 0}^{n - 1} \mathrm{floor}(\frac{a \times i + b}{m})$
86
86
 
87
87
  ### Verified
88
88
 
89
- [ALPC: C \- Floor Sum](https://atcoder.jp/contests/practice2/tasks/practice2_c)
89
+ [ALPC: C - Floor Sum](https://atcoder.jp/contests/practice2/tasks/practice2_c)
90
90
  - [ACコード 426ms 2020/9/14](https://atcoder.jp/contests/practice2/submissions/16735215)
91
91
 
92
92
  ## 参考リンク
@@ -107,7 +107,7 @@ $\sum_{i = 0}^{n - 1} \mathrm{floor}(\frac{a \times i + b}{m})$
107
107
  - [本家ライブラリの実装コード internal_math.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/internal_math.hpp)
108
108
  - [本家ライブラリのテストコード math_test.cpp](https://github.com/atcoder/ac-library/blob/master/test/unittest/math_test.cpp)
109
109
  - [本家ライブラリのドキュメント math.md](https://github.com/atcoder/ac-library/blob/master/document_ja/math.md)
110
- - [Relax the constraints of floor\_sum? · Issue \#33 · atcoder/ac\-library](https://github.com/atcoder/ac-library/issues/33)
110
+ - [Relax the constraints of floor\_sum? · Issue \#33 · atcoder/ac-library](https://github.com/atcoder/ac-library/issues/33)
111
111
 
112
112
  ## Q&A
113
113
 
@@ -87,9 +87,9 @@ graph.edges
87
87
 
88
88
  ## Verified
89
89
 
90
- [ALPC: D \- Maxflow](https://atcoder.jp/contests/practice2/tasks/practice2_d)
90
+ [ALPC: D - Maxflow](https://atcoder.jp/contests/practice2/tasks/practice2_d)
91
91
  - [ACコード 211ms 2020/9/17](https://atcoder.jp/contests/practice2/submissions/16789801)
92
- - [ALPC: D解説 \- Qiita](https://qiita.com/magurofly/items/bfaf6724418bfde86bd0)
92
+ - [ALPC: D解説 - Qiita](https://qiita.com/magurofly/items/bfaf6724418bfde86bd0)
93
93
 
94
94
  ## 参考リンク
95
95
 
@@ -108,7 +108,7 @@ graph.edges
108
108
 
109
109
  ### `flow`メソッドの`flow_limit`のデフォルトは 何故`1 << 64`
110
110
 
111
- 記憶になく、深い意味はないです。
111
+ 意味はないです。
112
112
  `Float::MAX`や`Float::INFINITY`でも良さそうですが、遅くならないでしょうか。
113
113
 
114
114
  ### 辺にStructは使わないの
@@ -119,10 +119,7 @@ Structを使った方がコードがスリムになって上級者ぽくもあ
119
119
 
120
120
  ### `_`始まりの変数の意図は
121
121
 
122
- ちょっと紛らわしいのですが、別々に2種類の意図があります。
123
-
124
- 1. `_e`や`_re`は、本家ACLコードと一緒に読みやすいように、変数名を合わせています。
125
- 2. `_rev`は、`each`で回す都合上吐き出すけれど使わないので、「使わない」という意図で`_`始まりにしています。
122
+ `_rev`は、`each`で回す都合上吐き出すけれど使わないので、「使わない」という意図で`_`始まりにしています。
126
123
 
127
124
  ```ruby
128
125
  @g[q].each do |(to, _rev, cap)|
@@ -73,7 +73,7 @@ graph.edges
73
73
 
74
74
  ## Verified
75
75
 
76
- [ALPC: E \- MinCostFlow](https://atcoder.jp/contests/practice2/tasks/practice2_e)
76
+ [ALPC: E - MinCostFlow](https://atcoder.jp/contests/practice2/tasks/practice2_e)
77
77
  - [1213ms 2020/9/17](https://atcoder.jp/contests/practice2/submissions/16792967)
78
78
 
79
79
  ## 参考リンク
@@ -86,17 +86,18 @@ graph.edges
86
86
  - [本家ライブラリの実装コード mincostflow.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/mincostflow.hpp)
87
87
  - [本家ライブラリのテストコード mincostflow_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/unittest/mincostflow_test.cpp)
88
88
 
89
- ## Q&A
89
+ ## 備考
90
90
 
91
91
  ### エイリアスの意図は
92
92
 
93
- 本家ライブラリの最小費用流の方のメソッド名が長いので、エイリアスを持たせています。本家ライブラリの最大流の方のメソッド名は短いので、不思議です。
93
+ 本家ライブラリの最小費用流の方のメソッド名が長いので、エイリアスを持たせています。
94
+ 本家ライブラリの最大流の方のメソッド名は短いので、不思議です。
94
95
 
95
96
  ### `Float::INFINITY`ではなく、`Float::MAX`を使う意図とは
96
97
 
97
98
  特に検証してないので、何の数値がいいのか検証したいです。
98
99
 
99
- `Integer`クラスでも良いよいな気がしました。
100
+ `Integer`クラスでも良いような気がしました。
100
101
 
101
102
  ### 辺にStructは使わないの
102
103
 
@@ -199,9 +199,9 @@ p 12.to_m == 1 #=> true
199
199
 
200
200
  ## Verified
201
201
 
202
- - [ABC156: D \- Bouquet](https://atcoder.jp/contests/abc156/tasks/abc156_d) 2020/2/22開催
202
+ - [ABC156: D - Bouquet](https://atcoder.jp/contests/abc156/tasks/abc156_d) 2020/2/22開催
203
203
  - [ACコード 138ms 2020/10/5](https://atcoder.jp/contests/abc156/submissions/17205940)
204
- - [ARC009: C \- 高橋君、24歳](https://atcoder.jp/contests/arc009/tasks/arc009_3) 2012/10/20開催
204
+ - [ARC009: C - 高橋君、24歳](https://atcoder.jp/contests/arc009/tasks/arc009_3) 2012/10/20開催
205
205
  - [ACコード 1075ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17206081)
206
206
  - [ACコード 901ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17208378)
207
207
 
@@ -221,8 +221,8 @@ p 12.to_m == 1 #=> true
221
221
  - Rubyリファレンスマニュアル
222
222
  - [class Numeric \(Ruby 2\.7\.0 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/class/Numeric.html)
223
223
  - その他
224
- - [modint 構造体を使ってみませんか? \(C\+\+\) \- noshi91のメモ](https://noshi91.hatenablog.com/entry/2019/03/31/174006)(2019/3/31)
225
- - [Pythonでmodintを実装してみた \- Qiita](https://qiita.com/wotsushi/items/c936838df992b706084c)(2019/4/1)
224
+ - [modint 構造体を使ってみませんか? \(C\+\+\) - noshi91のメモ](https://noshi91.hatenablog.com/entry/2019/03/31/174006)(2019/3/31)
225
+ - [Pythonでmodintを実装してみた - Qiita](https://qiita.com/wotsushi/items/c936838df992b706084c)(2019/4/1)
226
226
  - [C#版のModIntのドキュメント](https://github.com/key-moon/ac-library-cs/blob/master/document_ja/modint.md)
227
227
 
228
228
 
data/document_ja/scc.md CHANGED
@@ -50,17 +50,18 @@ graph.scc
50
50
 
51
51
  ## Verified
52
52
 
53
- - [ALPC: G \- SCC](https://atcoder.jp/contests/practice2/tasks/practice2_g)
54
- - [2538ms 2020/9/8](https://atcoder.jp/contests/practice2/submissions/16569175)
55
- - [競プロ典型 90 問: 021 - Come Back in One Piece][https://atcoder.jp/contests/typical90/tasks/typical90_u]
53
+ - [ALPC: G - SCC](https://atcoder.jp/contests/practice2/tasks/practice2_g)
54
+ - [Ruby2.7 1848ms 2022/11/22](https://atcoder.jp/contests/practice2/submissions/36708506)
55
+ - [競プロ典型 90 問: 021 - Come Back in One Piece](https://atcoder.jp/contests/typical90/tasks/typical90_u)
56
+ - [Ruby2.7 471ms 2021/6/15](https://atcoder.jp/contests/typical90/submissions/23487102)
56
57
 
57
58
  # 参考リンク
58
59
 
59
60
  - 当ライブラリ
60
- - [当ライブラリの実装コード scc\.rb](https://github.com/universato/ac-library-rb/blob/master/lib/scc.rb)
61
- - [当ライブラリの実装コード scc_test\.rb](https://github.com/universato/ac-library-rb/blob/master/test/scc_test.rb)
61
+ - [当ライブラリの実装コード scc.rb](https://github.com/universato/ac-library-rb/blob/master/lib/scc.rb)
62
+ - [当ライブラリの実装コード scc_test.rb](https://github.com/universato/ac-library-rb/blob/master/test/scc_test.rb)
62
63
  - 本家ライブラリ
63
- - [本家ライブラリの実装コード scc\.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/scc.hpp)
64
- - [本家ライブラリのドキュメント scc\.md](https://github.com/atcoder/ac-library/blob/master/document_ja/scc.md)
64
+ - [本家ライブラリの実装コード scc.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/scc.hpp)
65
+ - [本家ライブラリのドキュメント scc.md](https://github.com/atcoder/ac-library/blob/master/document_ja/scc.md)
65
66
  - その他
66
- - [強連結成分分解の意味とアルゴリズム \| 高校数学の美しい物語](https://mathtrain.jp/kyorenketsu)
67
+ - [強連結成分分解の意味とアルゴリズム | 高校数学の美しい物語](https://mathtrain.jp/kyorenketsu)
@@ -141,11 +141,11 @@ Segtree上で`0 <= l <= r`の範囲で、`f(prod(l, r))`の結果を二分探索
141
141
 
142
142
  ## Verified
143
143
 
144
- - [ALPC: J \- Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
144
+ - [ALPC: J - Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
145
145
  - [AC Code(884ms) max_right](https://atcoder.jp/contests/practice2/submissions/23196480)
146
146
  - [AC Code(914ms) min_left](https://atcoder.jp/contests/practice2/submissions/23197311)
147
147
 
148
- - [ABC185: F \- Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
148
+ - [ABC185: F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
149
149
  - xorのセグメントツリーの基本的な典型問題です。FenwickTree(BIT)をxorに改造するだけでも解けます。
150
150
  - [ACコード(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): 通常のSegtree解。
151
151
  - [ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT)のxor改造版。
@@ -1,3 +1,3 @@
1
1
  module AcLibraryRb
2
- VERSION = "0.6.1".freeze
2
+ VERSION = "0.7.0".freeze
3
3
  end
data/lib/convolution.rb CHANGED
@@ -124,7 +124,7 @@ class Convolution
124
124
  end
125
125
 
126
126
  # [EXPERIMENTAL]
127
- def convolution(a, b, mod: 998244353, k: 35, z: 99)
127
+ def convolution(a, b, mod: 998_244_353, k: 35, z: 99)
128
128
  n = a.size
129
129
  m = b.size
130
130
  return [] if n == 0 || m == 0
data/lib/dsu.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # Disjoint Set Union
2
2
  class DSU
3
- def initialize(n)
3
+ def initialize(n = 0)
4
4
  @n = n
5
5
  @parent_or_size = Array.new(n, -1)
6
6
  # root node: -1 * component size
@@ -35,6 +35,15 @@ class DSU
35
35
  alias root leader
36
36
  alias find leader
37
37
 
38
+ def [](a)
39
+ if @n <= a
40
+ @parent_or_size.concat([-1] * (a - @n + 1))
41
+ @n = @parent_or_size.size
42
+ end
43
+
44
+ @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = self[@parent_or_size[a]])
45
+ end
46
+
38
47
  def size(a)
39
48
  -@parent_or_size[leader(a)]
40
49
  end
@@ -42,6 +51,10 @@ class DSU
42
51
  def groups
43
52
  (0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
44
53
  end
54
+
55
+ def to_s
56
+ "<#{self.class}: @n=#{@n}, #{@parent_or_size}>"
57
+ end
45
58
  end
46
59
 
47
60
  UnionFind = DSU
data/lib/fenwick_tree.rb CHANGED
@@ -59,4 +59,8 @@ class FenwickTree
59
59
  res
60
60
  end
61
61
  alias left_sum _sum
62
+
63
+ def to_s
64
+ "<#{self.class}: @size=#{@size}, (#{@data[1..].join(', ')})>"
65
+ end
62
66
  end
data/lib/lazy_segtree.rb CHANGED
@@ -153,9 +153,7 @@ class LazySegtree
153
153
  sm = @e
154
154
 
155
155
  loop do
156
- while l.even?
157
- l >>= 1
158
- end
156
+ l >>= 1 while l.even?
159
157
  unless g.call(@op.call(sm, @d[l]))
160
158
  while l < @size
161
159
  push(l)
@@ -183,9 +181,7 @@ class LazySegtree
183
181
 
184
182
  loop do
185
183
  r -= 1
186
- while r > 1 && r.odd?
187
- r /= 2
188
- end
184
+ r /= 2 while r > 1 && r.odd?
189
185
  unless g.call(@op.call(@d[r], sm))
190
186
  while r < @size
191
187
  push(r)
data/lib/max_flow.rb CHANGED
@@ -36,39 +36,40 @@ class MaxFlow
36
36
 
37
37
  # return edge = [from, to, cap, flow]
38
38
  def [](i)
39
- _e = @g[@pos[i][0]][@pos[i][1]]
40
- _re = @g[_e[0]][_e[1]]
41
- [@pos[i][0], _e[0], _e[-1] + _re[-1], _re[-1]]
39
+ from, from_id = @pos[i]
40
+
41
+ to, to_id, cap = @g[from][from_id] # edge
42
+ _from, _from_id, flow = @g[to][to_id] # reverse edge
43
+
44
+ [from, to, cap + flow, flow]
42
45
  end
43
46
  alias get_edge []
44
47
  alias edge []
45
48
 
46
49
  def edges
47
- @pos.map do |(from, id)|
48
- _e = @g[from][id]
49
- _re = @g[_e[0]][_e[1]]
50
- [from, _e[0], _e[-1] + _re[-1], _re[-1]]
50
+ @pos.map do |(from, from_id)|
51
+ to, to_id, cap = @g[from][from_id]
52
+ _from, _from_id, flow = @g[to][to_id]
53
+ [from, to, cap + flow, flow]
51
54
  end
52
55
  end
53
56
 
54
57
  def change_edge(i, new_cap, new_flow)
55
- _e = @g[@pos[i][0]][@pos[i][1]]
56
- _re = @g[_e[0]][_e[1]]
57
- _e[2] = new_cap - new_flow
58
- _re[2] = new_flow
58
+ from, from_id = @pos[i]
59
+
60
+ e = @g[from][from_id]
61
+ re = @g[e[0]][e[1]]
62
+ e[2] = new_cap - new_flow
63
+ re[2] = new_flow
59
64
  end
60
65
 
61
66
  def flow(s, t, flow_limit = 1 << 64)
62
- level = Array.new(@n)
63
- iter = Array.new(@n)
64
- que = []
65
-
66
67
  flow = 0
67
68
  while flow < flow_limit
68
- bfs(s, t, level, que)
69
+ level = bfs(s, t)
69
70
  break if level[t] == -1
70
71
 
71
- iter.fill(0)
72
+ iter = [0] * @n
72
73
  while flow < flow_limit
73
74
  f = dfs(t, flow_limit - flow, s, level, iter)
74
75
  break if f == 0
@@ -98,22 +99,22 @@ class MaxFlow
98
99
 
99
100
  private
100
101
 
101
- def bfs(s, t, level, que)
102
- level.fill(-1)
102
+ def bfs(s, t)
103
+ level = Array.new(@n, -1)
103
104
  level[s] = 0
104
- que.clear
105
- que << s
105
+ que = [s]
106
106
 
107
107
  while (v = que.shift)
108
- @g[v].each do |e|
109
- next if e[2] == 0 || level[e[0]] >= 0
108
+ @g[v].each do |u, _, cap|
109
+ next if cap == 0 || level[u] >= 0
110
110
 
111
- level[e[0]] = level[v] + 1
112
- return nil if e[0] == t
111
+ level[u] = level[v] + 1
112
+ return level if u == t
113
113
 
114
- que << e[0]
114
+ que << u
115
115
  end
116
116
  end
117
+ level
117
118
  end
118
119
 
119
120
  def dfs(v, up, s, level, iter)
data/lib/modint.rb CHANGED
@@ -4,7 +4,7 @@ require_relative './core_ext/modint.rb'
4
4
  class ModInt < Numeric
5
5
  class << self
6
6
  def set_mod(mod)
7
- raise ArgumentError unless mod.is_a? Integer and 1 <= mod
7
+ raise ArgumentError unless mod.is_a?(Integer) && (1 <= mod)
8
8
 
9
9
  $_mod = mod
10
10
  $_mod_is_prime = ModInt.prime?(mod)
@@ -26,7 +26,7 @@ class ModInt < Numeric
26
26
 
27
27
  def prime?(n)
28
28
  return false if n <= 1
29
- return true if n == 2 or n == 7 or n == 61
29
+ return true if (n == 2) || (n == 7) || (n == 61)
30
30
  return false if (n & 1) == 0
31
31
 
32
32
  d = n - 1
@@ -34,11 +34,11 @@ class ModInt < Numeric
34
34
  [2, 7, 61].each do |a|
35
35
  t = d
36
36
  y = a.pow(t, n)
37
- while t != n - 1 and y != 1 and y != n - 1
37
+ while (t != n - 1) && (y != 1) && (y != n - 1)
38
38
  y = y * y % n
39
39
  t <<= 1
40
40
  end
41
- return false if y != n - 1 and (t & 1) == 0
41
+ return false if (y != n - 1) && ((t & 1) == 0)
42
42
  end
43
43
  true
44
44
  end
@@ -13,11 +13,17 @@ class PriorityQueue
13
13
  heapify
14
14
  end
15
15
 
16
+ def self.[](*array, &comp)
17
+ new(array, &comp)
18
+ end
19
+
16
20
  attr_reader :heap
21
+ alias to_a heap
17
22
 
18
23
  # Push new element to the heap.
19
24
  def push(item)
20
25
  shift_down(0, @heap.push(item).size - 1)
26
+ self
21
27
  end
22
28
 
23
29
  alias << push
@@ -46,6 +52,14 @@ class PriorityQueue
46
52
  @heap.empty?
47
53
  end
48
54
 
55
+ def size
56
+ @heap.size
57
+ end
58
+
59
+ def to_s
60
+ "<#{self.class}: @heap:(#{heap.join(', ')}), @comp:<#{@comp.class} #{@comp.source_location.join(':')}>>"
61
+ end
62
+
49
63
  private
50
64
 
51
65
  def heapify
data/lib/scc.rb CHANGED
@@ -8,7 +8,7 @@ class SCC
8
8
 
9
9
  # add directed edge
10
10
  def add_edge(from, to)
11
- unless 0 <= from && from < @n and 0 <= to && to < @n
11
+ unless 0 <= from && from < @n && 0 <= to && to < @n
12
12
  msg = "Wrong params: from=#{from} and to=#{to} must be in 0...#{@n}"
13
13
  raise ArgumentError.new(msg)
14
14
  end
data/lib/two_sat.rb CHANGED
@@ -12,7 +12,7 @@ class TwoSAT
12
12
  attr_reader :answer
13
13
 
14
14
  def add_clause(i, f, j, g)
15
- unless 0 <= i && i < @n and 0 <= j && j < @n
15
+ unless 0 <= i && i < @n && 0 <= j && j < @n
16
16
  raise ArgumentError.new("i:#{i} and j:#{j} must be in (0...#{@n})")
17
17
  end
18
18
 
@@ -125,7 +125,7 @@ module AcLibraryRb
125
125
  end
126
126
 
127
127
  # [EXPERIMENTAL]
128
- def convolution(a, b, mod: 998244353, k: 35, z: 99)
128
+ def convolution(a, b, mod: 998_244_353, k: 35, z: 99)
129
129
  n = a.size
130
130
  m = b.size
131
131
  return [] if n == 0 || m == 0
@@ -1,7 +1,7 @@
1
1
  module AcLibraryRb
2
2
  # Disjoint Set Union
3
3
  class DSU
4
- def initialize(n)
4
+ def initialize(n = 0)
5
5
  @n = n
6
6
  @parent_or_size = Array.new(n, -1)
7
7
  # root node: -1 * component size
@@ -36,6 +36,15 @@ module AcLibraryRb
36
36
  alias root leader
37
37
  alias find leader
38
38
 
39
+ def [](a)
40
+ if @n <= a
41
+ @parent_or_size.concat([-1] * (a - @n + 1))
42
+ @n = @parent_or_size.size
43
+ end
44
+
45
+ @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = self[@parent_or_size[a]])
46
+ end
47
+
39
48
  def size(a)
40
49
  -@parent_or_size[leader(a)]
41
50
  end
@@ -43,6 +52,10 @@ module AcLibraryRb
43
52
  def groups
44
53
  (0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
45
54
  end
55
+
56
+ def to_s
57
+ "<#{self.class}: @n=#{@n}, #{@parent_or_size}>"
58
+ end
46
59
  end
47
60
 
48
61
  UnionFind = DSU
@@ -60,5 +60,9 @@ module AcLibraryRb
60
60
  res
61
61
  end
62
62
  alias left_sum _sum
63
+
64
+ def to_s
65
+ "<#{self.class}: @size=#{@size}, (#{@data[1..].join(', ')})>"
66
+ end
63
67
  end
64
68
  end
@@ -154,9 +154,7 @@ module AcLibraryRb
154
154
  sm = @e
155
155
 
156
156
  loop do
157
- while l.even?
158
- l >>= 1
159
- end
157
+ l >>= 1 while l.even?
160
158
  unless g.call(@op.call(sm, @d[l]))
161
159
  while l < @size
162
160
  push(l)
@@ -184,9 +182,7 @@ module AcLibraryRb
184
182
 
185
183
  loop do
186
184
  r -= 1
187
- while r > 1 && r.odd?
188
- r /= 2
189
- end
185
+ r /= 2 while r > 1 && r.odd?
190
186
  unless g.call(@op.call(@d[r], sm))
191
187
  while r < @size
192
188
  push(r)
@@ -37,39 +37,40 @@ module AcLibraryRb
37
37
 
38
38
  # return edge = [from, to, cap, flow]
39
39
  def [](i)
40
- _e = @g[@pos[i][0]][@pos[i][1]]
41
- _re = @g[_e[0]][_e[1]]
42
- [@pos[i][0], _e[0], _e[-1] + _re[-1], _re[-1]]
40
+ from, from_id = @pos[i]
41
+
42
+ to, to_id, cap = @g[from][from_id] # edge
43
+ _from, _from_id, flow = @g[to][to_id] # reverse edge
44
+
45
+ [from, to, cap + flow, flow]
43
46
  end
44
47
  alias get_edge []
45
48
  alias edge []
46
49
 
47
50
  def edges
48
- @pos.map do |(from, id)|
49
- _e = @g[from][id]
50
- _re = @g[_e[0]][_e[1]]
51
- [from, _e[0], _e[-1] + _re[-1], _re[-1]]
51
+ @pos.map do |(from, from_id)|
52
+ to, to_id, cap = @g[from][from_id]
53
+ _from, _from_id, flow = @g[to][to_id]
54
+ [from, to, cap + flow, flow]
52
55
  end
53
56
  end
54
57
 
55
58
  def change_edge(i, new_cap, new_flow)
56
- _e = @g[@pos[i][0]][@pos[i][1]]
57
- _re = @g[_e[0]][_e[1]]
58
- _e[2] = new_cap - new_flow
59
- _re[2] = new_flow
59
+ from, from_id = @pos[i]
60
+
61
+ e = @g[from][from_id]
62
+ re = @g[e[0]][e[1]]
63
+ e[2] = new_cap - new_flow
64
+ re[2] = new_flow
60
65
  end
61
66
 
62
67
  def flow(s, t, flow_limit = 1 << 64)
63
- level = Array.new(@n)
64
- iter = Array.new(@n)
65
- que = []
66
-
67
68
  flow = 0
68
69
  while flow < flow_limit
69
- bfs(s, t, level, que)
70
+ level = bfs(s, t)
70
71
  break if level[t] == -1
71
72
 
72
- iter.fill(0)
73
+ iter = [0] * @n
73
74
  while flow < flow_limit
74
75
  f = dfs(t, flow_limit - flow, s, level, iter)
75
76
  break if f == 0
@@ -99,22 +100,22 @@ module AcLibraryRb
99
100
 
100
101
  private
101
102
 
102
- def bfs(s, t, level, que)
103
- level.fill(-1)
103
+ def bfs(s, t)
104
+ level = Array.new(@n, -1)
104
105
  level[s] = 0
105
- que.clear
106
- que << s
106
+ que = [s]
107
107
 
108
108
  while (v = que.shift)
109
- @g[v].each do |e|
110
- next if e[2] == 0 || level[e[0]] >= 0
109
+ @g[v].each do |u, _, cap|
110
+ next if cap == 0 || level[u] >= 0
111
111
 
112
- level[e[0]] = level[v] + 1
113
- return nil if e[0] == t
112
+ level[u] = level[v] + 1
113
+ return level if u == t
114
114
 
115
- que << e[0]
115
+ que << u
116
116
  end
117
117
  end
118
+ level
118
119
  end
119
120
 
120
121
  def dfs(v, up, s, level, iter)