ac-library-rb 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -0
  3. data/README.ja.md +102 -4
  4. data/README.md +73 -1
  5. data/Rakefile +2 -1
  6. data/ac-library-rb.gemspec +3 -2
  7. data/bin/lock_lib.rb +13 -7
  8. data/document_en/dsu.md +2 -2
  9. data/document_en/lazy_segtree.md +20 -4
  10. data/document_en/max_flow.md +1 -1
  11. data/document_en/min_cost_flow.md +1 -1
  12. data/document_en/segtree.md +36 -3
  13. data/document_en/two_sat.md +1 -1
  14. data/document_ja/dsu.md +1 -3
  15. data/document_ja/lazy_segtree.md +63 -19
  16. data/document_ja/max_flow.md +1 -1
  17. data/document_ja/min_cost_flow.md +1 -1
  18. data/document_ja/scc.md +4 -3
  19. data/document_ja/segtree.md +49 -8
  20. data/document_ja/two_sat.md +1 -1
  21. data/lib/ac-library-rb/version.rb +1 -1
  22. data/lib/convolution.rb +21 -0
  23. data/lib/core_ext/all.rb +11 -0
  24. data/lib/dsu.rb +9 -6
  25. data/lib/fenwick_tree.rb +22 -8
  26. data/lib/floor_sum.rb +33 -10
  27. data/lib/lazy_segtree.rb +83 -10
  28. data/lib/max_flow.rb +10 -4
  29. data/lib/min_cost_flow.rb +13 -7
  30. data/lib/modint.rb +3 -1
  31. data/lib/scc.rb +21 -13
  32. data/lib/segtree.rb +38 -26
  33. data/lib/suffix_array.rb +8 -8
  34. data/lib/two_sat.rb +5 -3
  35. data/lib_lock/ac-library-rb.rb +2 -0
  36. data/lib_lock/ac-library-rb/convolution.rb +21 -0
  37. data/lib_lock/ac-library-rb/core_ext/all.rb +11 -0
  38. data/lib_lock/ac-library-rb/core_ext/modint.rb +3 -3
  39. data/lib_lock/ac-library-rb/dsu.rb +9 -6
  40. data/lib_lock/ac-library-rb/fenwick_tree.rb +22 -8
  41. data/lib_lock/ac-library-rb/floor_sum.rb +33 -10
  42. data/lib_lock/ac-library-rb/lazy_segtree.rb +83 -10
  43. data/lib_lock/ac-library-rb/max_flow.rb +10 -4
  44. data/lib_lock/ac-library-rb/min_cost_flow.rb +13 -7
  45. data/lib_lock/ac-library-rb/modint.rb +3 -1
  46. data/lib_lock/ac-library-rb/scc.rb +21 -13
  47. data/lib_lock/ac-library-rb/segtree.rb +38 -26
  48. data/lib_lock/ac-library-rb/suffix_array.rb +8 -8
  49. data/lib_lock/ac-library-rb/two_sat.rb +5 -3
  50. metadata +20 -4
@@ -17,7 +17,7 @@ it decides whether there is a truth assignment that satisfies all clauses.
17
17
 
18
18
  ## Class Methods
19
19
 
20
- ### new(n = 0) -> TwoSAT
20
+ ### new(n) -> TwoSAT
21
21
 
22
22
  ```ruby
23
23
  ts = TwoSAT.new(n)
data/document_ja/dsu.md CHANGED
@@ -30,7 +30,7 @@ p d.size(2) # => 2
30
30
 
31
31
  ## 特異メソッド
32
32
 
33
- ### new(n = 0) -> DSU
33
+ ### new(n) -> DSU
34
34
 
35
35
  ```rb
36
36
  d = DSU.new(n)
@@ -48,9 +48,7 @@ d = DSU.new(n)
48
48
  **エイリアス**
49
49
 
50
50
  - `DSU`
51
- - `DisjointSetUnion`
52
51
  - `UnionFind`
53
- - `UnionFindTree`
54
52
 
55
53
  ## インスタンスメソッド
56
54
 
@@ -8,10 +8,10 @@
8
8
 
9
9
  ## 特異メソッド
10
10
 
11
- ### new(v, e, id, op, mapping, composition)
11
+ ### new(v, e, id){ }
12
12
 
13
13
  ```ruby
14
- seg = LazySegtree.new(v, e, id, op, mapping, compositon)
14
+ seg = LazySegtree.new(v, e, id)
15
15
  ```
16
16
 
17
17
  第1引数は、`Integer`または`Array`です。
@@ -21,8 +21,22 @@ seg = LazySegtree.new(v, e, id, op, mapping, compositon)
21
21
 
22
22
  第2引数`e`は、単位元です。ブロックで二項演算`op(x, y)`を定義することで、モノイドを定義する必要があります。
23
23
 
24
+ また、インスタンス作成後に、`LazySegtree#set_mapping{ }`と`LazySegment#set_composition{ }`を用い、適切にインスタンス変数にprocを設定する必要があります。
25
+
24
26
  **計算量** `O(n)`
25
27
 
28
+ ### new(v, op, e, mapping, composition, id)
29
+ ### new(v, e, id, op, mapping, composition)
30
+
31
+ ```ruby
32
+ seg = LazySegtree.new(v, op, e, mapping, compositon, id)
33
+ seg = LazySegtree.new(v, e, id, op, mapping, compositon)
34
+ ```
35
+
36
+ 前者は、本家ライブラリに合わせた引数の順番。
37
+ 後者は、procを後ろにまとめた引数の順番で、これは非推奨。
38
+ 内部で、第2引数がprocかどうかで、場合分けしています。
39
+
26
40
  ## インスタンスメソッド
27
41
 
28
42
  ### set(pos, x)
@@ -53,7 +67,7 @@ seg.get(pos)
53
67
  seg.prod(l, r)
54
68
  ```
55
69
 
56
- `op(a[l], ..., a[r - 1])` を返します。
70
+ `op(a[l], ..., a[r - 1])` を返します。引数は半開区間です。`l == r`のとき、単位元`e`を返します。
57
71
 
58
72
  **制約** `0 ≦ l ≦ r ≦ n`
59
73
 
@@ -65,19 +79,24 @@ seg.prod(l, r)
65
79
  seg.all_prod
66
80
  ```
67
81
 
68
- `op(a[0], ..., a[n - 1])` を返します。
82
+ `op(a[0], ..., a[n - 1])` を返します。サイズが0のときは、単位元`e`を返します。
69
83
 
70
84
  **計算量** `O(1)`
71
85
 
72
86
  ### apply(pos, val)
87
+ ### apply(s, r, val)
73
88
 
74
89
  ```ruby
75
90
  seg.apply(pos, val)
91
+ seg.apply(l, r, val)
76
92
  ```
77
93
 
78
- 本家コードで引数が3つのとき実装について、当ライブラリでは`range_apply`という名称で実装しています。実行時間を計測して問題なさそうなら、`apply`メソッドに2引数と3引数の両方に対応できるようにします。
94
+ 1. `a[p] = f(a[p])`
95
+ 2. 半開区間`i = l..r`について`a[i] = f(a[i])`
79
96
 
80
- **制約** `0 ≦ pos < n`
97
+ **制約**
98
+ 1. `0 ≦ pos < n`
99
+ 2. `0 ≦ l ≦ r ≦ n`
81
100
 
82
101
  **計算量** `O(log n)`
83
102
 
@@ -87,28 +106,44 @@ seg.apply(pos, val)
87
106
  seg.range_apply(l, r, val)
88
107
  ```
89
108
 
109
+ 3引数の`apply`を呼んだときに、内部で呼ばれるメソッド。
110
+ 直接、`range_apply`を呼ぶこともできる。
111
+
90
112
  **制約** `0 ≦ l ≦ r ≦ n`
91
113
 
92
114
  **計算量** `O(log n)`
93
115
 
94
- ### max_right
116
+ ### max_right(l){ } -> Integer
95
117
 
96
- [TODO] 暇な誰かが書く。
118
+ LazySegtree上で、二分探索をします。
97
119
 
98
- ### min_left
120
+ **制約** `0 ≦ l ≦ n`
99
121
 
100
- [TODO] コード側の実装ができていないです。
122
+ **計算量** `O(log n)`
123
+
124
+ ### min_left(r){ } -> Integer
125
+
126
+ LazySegtree上で、二分探索をします。
127
+
128
+ **制約** `0 ≦ r ≦ n`
129
+
130
+ **計算量** `O(log n)`
101
131
 
102
132
  ## Verified
103
133
 
104
- 問題のリンクです。コードはないですが、Verified済みです。
105
- - [AIZU ONLINE JUDGE DSL\_2\_F RMQ and RUQ](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_F)
106
- - [AIZU ONLINE JUDGE DSL\_2\_G RSQ and RAQ](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G)
134
+ 問題のリンクです。Verified済みです。解答はテストコードをご参考ください。
135
+ - [AIZU ONLINE JUDGE DSL\_2\_F RMQ and RUQ](https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_F) ([旧DSL_2_F](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_F))
136
+ - [AIZU ONLINE JUDGE DSL\_2\_G RSQ and RAQ](https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_G) ([旧DSL_2_G](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G))
137
+ - [AIZU ONLINE JUDGE DSL\_2\_H RMQ and RAQ](https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_H) ([旧DSL_2_H](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H))
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))
107
139
 
108
140
  以下の問題は、Rubyでは実行時間が厳しくTLEになりACできてないです。
109
141
  - [ALPC: K \- Range Affine Range Sum](https://atcoder.jp/contests/practice2/tasks/practice2_k)
110
142
  - [ALPC: L \- Lazy Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_l)
111
143
 
144
+ 下記は、ジャッジにだしてないが、サンプルに正解。`max_right`, `min_left`を使う問題。
145
+ - [Quora Programming Challenge 2021: Skyscraper](https://jonathanirvin.gs/files/division2_3d16774b0423.pdf#page=5)
146
+
112
147
  ## 参考リンク
113
148
 
114
149
  - 当ライブラリ
@@ -120,16 +155,25 @@ seg.range_apply(l, r, val)
120
155
  - [本家ライブラリの実装コード lazysegtree.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/lazysegtree.hpp)
121
156
  - [本家ライブラリのテストコード lazysegtree_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/unittest/lazysegtree_test.cpp)
122
157
  - セグメントツリーについて
123
- - [セグメント木をソラで書きたいあなたに \- hogecoder](https://tsutaj.hatenablog.com/entry/2017/03/29/204841)
124
- - [遅延評価セグメント木をソラで書きたいあなたに \- hogecoder](https://tsutaj.hatenablog.com/entry/2017/03/30/224339)
158
+ - [2017/3 hogecoder: セグメント木をソラで書きたいあなたに](https://tsutaj.hatenablog.com/entry/2017/03/29/204841)
159
+ - [2017/3 hogecoder: 遅延評価セグメント木をソラで書きたいあなたに](https://tsutaj.hatenablog.com/entry/2017/03/30/224339)
160
+ - [2017/7 はまやんはまやんはまやん: 競技プログラミングにおけるセグメントツリー問題まとめ](https://blog.hamayanhamayan.com/entry/2017/07/08/173120)
161
+ - [2020/2 ageprocpp Qiita: Segment Treeことはじめ【後編】](https://qiita.com/ageprocpp/items/9ea58ac181d31cfdfe02)
125
162
  - AtCooderLibrary(ACL)のLazySegtreeについて
126
- - [使い方 \- ARMERIA 2020/9/22](https://betrue12.hateblo.jp/entry/2020/09/22/194541)
127
- - [チートシート \- ARMERIA 2020/9/23](https://betrue12.hateblo.jp/entry/2020/09/23/005940)
128
- - [ACLPC: K–Range Affine Range Sumの解説 \|optのブログ 2020/9/27](https://opt-cp.com/cp/lazysegtree-aclpc-k/)
129
- - [ACL 基礎実装例集 \- buyoh\.hateblo\.jp 2020/9/27](https://buyoh.hateblo.jp/entry/2020/09/27/190144)
163
+ - [2020/9/22 ARMERIA: 使い方](https://betrue12.hateblo.jp/entry/2020/09/22/194541)
164
+ - [2020/9/23 ARMERIA: チートシート](https://betrue12.hateblo.jp/entry/2020/09/23/005940)
165
+ - [2020/9/27 optのブログ: ACLPC: K–Range Affine Range Sumの解説](https://opt-cp.com/cp/lazysegtree-aclpc-k/)
166
+ - [2020/9/27 buyoh.hateblo.jp: ACL 基礎実装例集](https://buyoh.hateblo.jp/entry/2020/09/27/190144)
130
167
 
131
168
  ## 本家ライブラリとの違い
132
169
 
133
170
  ### `ceil_pow2`ではなく、`bit_length`
134
171
 
135
172
  本家C++ライブラリは独自定義の`internal::ceil_pow2`関数を用いてますが、本ライブラリではRuby既存のメソッド`Integer#bit_length`を用いています。そちらの方が計測した結果、高速でした。
173
+
174
+ ## 問題点
175
+
176
+ ### ミュータブルな単位元
177
+
178
+ 本家ACL同様に、初期化の際に配列でも数値でもいいとなっている。
179
+ しかし、数値で要素数を指定した際に、ミュータブルなクラスでも同一オブジェクトで要素を作ってしまっている。
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 特異メソッド
6
6
 
7
- ### new(n = 0) -> MaxFlow
7
+ ### new(n) -> MaxFlow
8
8
 
9
9
  ```ruby
10
10
  graph = Maxflow.new(10)
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 特異メソッド
6
6
 
7
- ### new(n = 0) -> MinCostFlow
7
+ ### new(n) -> MinCostFlow
8
8
 
9
9
  ```ruby
10
10
  graph = MinCostFlow.new(10)
data/document_ja/scc.md CHANGED
@@ -6,7 +6,7 @@ Strongly Connected Components
6
6
 
7
7
  ## 特異メソッド
8
8
 
9
- ### new(n = 0) -> SCC
9
+ ### new(n) -> SCC
10
10
 
11
11
  ```ruby
12
12
  graph = SCC.new(6)
@@ -50,8 +50,9 @@ 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)
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]
55
56
 
56
57
  # 参考リンク
57
58
 
@@ -4,7 +4,8 @@
4
4
 
5
5
  ## 特異メソッド
6
6
 
7
- ### new(arg, e, &op) -> Segtree
7
+ ### new(arg, e){ |x, y| ... } -> Segtree
8
+ ### new(arg, op, e) -> Segtree
8
9
 
9
10
  ```rb
10
11
  seg = Segtree.new(arg, e) { |x, y| ... }
@@ -66,7 +67,7 @@ seg.get(pos)
66
67
  seg.prod(l, r)
67
68
  ```
68
69
 
69
- `op(a[l], ..., a[r - 1])` を返します。
70
+ `op(a[l], ..., a[r - 1])` を返します。引数は半開区間です。`l == r`のとき、単位元`e`を返します。
70
71
 
71
72
  **制約**
72
73
 
@@ -82,7 +83,7 @@ seg.prod(l, r)
82
83
  seg.all_prod
83
84
  ```
84
85
 
85
- `op(a[0], ..., a[n - 1])` を返します。
86
+ `op(a[0], ..., a[n - 1])` を返します。空のセグメントツリー、つまりサイズが0のとき、単位元`e`を返します。
86
87
 
87
88
  **計算量**
88
89
 
@@ -94,7 +95,24 @@ seg.all_prod
94
95
  seg.max_right(l, &f)
95
96
  ```
96
97
 
97
- Segtree上で二分探索をします。
98
+ Segtree上で`l <= r <= n`の範囲で、`f(prod(l, r))`の結果を二分探索をして条件に当てはまる`r`を返します。
99
+
100
+ 以下の条件を両方満たす `r` (`l <= r <= n`)を(いずれか一つ)返します。
101
+
102
+ - `r = l` もしくは `f(prod(l, r))`が`true`となる`r`
103
+ - `r = n` もしくは `f(prod(l, r + 1))`が`false`となる`r`
104
+
105
+ `prod(l, r)`は半開区間`[l, r)`であることに注意。
106
+
107
+ **制約**
108
+
109
+ - `f`を同じ引数で呼んだとき、返り値は同じ。
110
+ - `f(e)`が`true`
111
+ - `0 ≦ l ≦ n`
112
+
113
+ **計算量**
114
+
115
+ - `O(log n)`
98
116
 
99
117
  ### min_left(r, &f) -> Integer
100
118
 
@@ -102,13 +120,32 @@ Segtree上で二分探索をします。
102
120
  seg.min_left(r, &f)
103
121
  ```
104
122
 
105
- Segtree上で二分探索をします。
123
+ Segtree上で`0 <= l <= r`の範囲で、`f(prod(l, r))`の結果を二分探索をして条件に当てはまる`l`を返します。
124
+
125
+ 以下の条件を両方満たす `l` (`0 <= l <= r`)を(いずれか一つ)返します。
126
+
127
+ - `l = r` もしくは `f(prod(l, r))`が`true`となる`l`
128
+ - `l = 0` もしくは `f(prod(l - 1, r))`が`false`となる`l`
129
+
130
+ `prod(l, r)`は半開区間`[l, r)`であることに注意。
131
+
132
+ **制約**
133
+
134
+ - `f`を同じ引数で呼んだとき、返り値は同じ。
135
+ - `f(e)`が`true`
136
+ - `0 ≦ l ≦ n`
137
+
138
+ **計算量**
139
+
140
+ - `O(log n)`
106
141
 
107
142
  ## Verified
108
143
 
109
144
  - [ALPC: J \- Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
145
+ - [AC Code(884ms) max_right](https://atcoder.jp/contests/practice2/submissions/23196480)
146
+ - [AC Code(914ms) min_left](https://atcoder.jp/contests/practice2/submissions/23197311)
110
147
 
111
- - [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)
112
149
  - xorのセグメントツリーの基本的な典型問題です。FenwickTree(BIT)をxorに改造するだけでも解けます。
113
150
  - [ACコード(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): 通常のSegtree解。
114
151
  - [ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT)のxor改造版。
@@ -119,14 +156,18 @@ Segtree上で二分探索をします。
119
156
  - [当ライブラリの実装コード segtree.rb](https://github.com/universato/ac-library-rb/blob/master/lib/segtree.rb)
120
157
  - [当ライブラリのテストコード segtree.rb](https://github.com/universato/ac-library-rb/blob/master/test/segtree_test.rb)
121
158
  - テストコードも具体的な使い方として役に立つかもしれまん。
122
- - 本家
159
+ - 本家ライブラリ
123
160
  - [本家ライブラリのドキュメント segtree.md(GitHub)](https://github.com/atcoder/ac-library/blob/master/document_ja/segtree.md)
124
161
  - [本家のドキュメント appendix.md(GitHub)](https://github.com/atcoder/ac-library/blob/master/document_ja/appendix.md)
125
162
  - [本家ライブラリの実装コード segtree.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/segtree.hpp)
126
163
  - [本家ライブラリのテストコード segtree_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/unittest/segtree_test.cpp)
127
164
  - [本家ライブラリのサンプルコード segtree_practice.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/example/segtree_practice.cpp)
128
165
  - セグメントツリーについて
129
- - [セグメント木をソラで書きたいあなたに \- hogecoder](https://tsutaj.hatenablog.com/entry/2017/03/29/204841)
166
+ - [2017/3 hogecoder: セグメント木をソラで書きたいあなたに](https://tsutaj.hatenablog.com/entry/2017/03/29/204841)
167
+ - [2017/7 はまやんはまやんはまやん: 競技プログラミングにおけるセグメントツリー問題まとめ](https://blog.hamayanhamayan.com/entry/2017/07/08/173120)
168
+ - [2017/12 ei1333の日記: ちょっと変わったセグメント木の使い方](https://ei1333.hateblo.jp/entry/2017/12/14/000000)
169
+ スライドが二分探索について詳しい
170
+ - [2020/2 ageprocpp@Qiita: Segment Treeことはじめ【前編](https://qiita.com/ageprocpp/items/f22040a57ad25d04d199)
130
171
 
131
172
  ## 本家ライブラリとの違い等
132
173
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  ## 特異メソッド
17
17
 
18
- ### new(n = 0) -> TwoSAT
18
+ ### new(n) -> TwoSAT
19
19
 
20
20
  ```ruby
21
21
  ts = TwoSAT.new(n)
@@ -1,3 +1,3 @@
1
1
  module AcLibraryRb
2
- VERSION = "0.5.0".freeze
2
+ VERSION = "0.6.0".freeze
3
3
  end
data/lib/convolution.rb CHANGED
@@ -122,3 +122,24 @@ class Convolution
122
122
 
123
123
  private :batterfly, :batterfly_inv, :bsf, :calc_primitive_root
124
124
  end
125
+
126
+ # [EXPERIMENTAL]
127
+ def convolution(a, b, mod: 998244353, k: 35, z: 99)
128
+ n = a.size
129
+ m = b.size
130
+ return [] if n == 0 || m == 0
131
+
132
+ raise ArgumentError if a.min < 0 || b.min < 0
133
+
134
+ format = "%0#{k}x" # "%024x"
135
+ sa = ""
136
+ sb = ""
137
+ a.each{ |x| sa << (format % x) }
138
+ b.each{ |x| sb << (format % x) }
139
+
140
+ zero = '0'
141
+ s = zero * z + ("%x" % (sa.hex * sb.hex))
142
+ i = -(n + m - 1) * k - 1
143
+
144
+ Array.new(n + m - 1){ (s[i + 1..i += k] || zero).hex % mod }
145
+ end
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def to_fenwick_tree
3
+ FenwickTree.new(self)
4
+ end
5
+ alias to_fetree to_fenwick_tree
6
+
7
+ def to_priority_queue
8
+ PriorityQueue.new(self)
9
+ end
10
+ alias to_pq to_priority_queue
11
+ end
data/lib/dsu.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  # Disjoint Set Union
2
2
  class DSU
3
- def initialize(n = 0)
3
+ def initialize(n)
4
+ @n = n
5
+ @parent_or_size = Array.new(n, -1)
4
6
  # root node: -1 * component size
5
7
  # otherwise: parent
6
- @parent_or_size = Array.new(n, -1)
7
8
  end
8
9
 
9
- attr_accessor :parent_or_size
10
+ attr_reader :parent_or_size, :n
10
11
 
11
12
  def merge(a, b)
12
13
  x = leader(a)
@@ -25,6 +26,10 @@ class DSU
25
26
  alias same? same
26
27
 
27
28
  def leader(a)
29
+ unless 0 <= a && a < @n
30
+ raise ArgumentError.new, "#{a} is out of range (0...#{@n})"
31
+ end
32
+
28
33
  @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
29
34
  end
30
35
  alias root leader
@@ -39,6 +44,4 @@ class DSU
39
44
  end
40
45
  end
41
46
 
42
- UnionFind = DSU
43
- UnionFindTree = DSU
44
- DisjointSetUnion = DSU
47
+ UnionFind = DSU
data/lib/fenwick_tree.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  class FenwickTree
3
3
  attr_reader :data, :size
4
4
 
5
- def initialize(arg = 0)
5
+ def initialize(arg = nil)
6
6
  case arg
7
7
  when Array
8
8
  @size = arg.size
@@ -17,7 +17,7 @@ class FenwickTree
17
17
  @size = arg
18
18
  @data = Array.new(@size + 1, 0)
19
19
  else
20
- raise ArgumentError
20
+ raise ArgumentError.new("wrong argument. type is Array or Integer")
21
21
  end
22
22
  end
23
23
 
@@ -29,8 +29,25 @@ class FenwickTree
29
29
  end
30
30
  end
31
31
 
32
- def sum(l, r)
33
- _sum(r) - _sum(l)
32
+ # .sum(l, r) # [l, r) <- Original
33
+ # .sum(r) # [0, r) <- [Experimental]
34
+ # .sum(l..r) # [l, r] <- [Experimental]
35
+ def sum(a, b = nil)
36
+ if b
37
+ _sum(b) - _sum(a)
38
+ elsif a.is_a?(Range)
39
+ l = a.begin
40
+ l += @size if l < 0
41
+ if r = a.end
42
+ r += @size if r < 0
43
+ r += 1 unless a.exclude_end?
44
+ else
45
+ r = @size
46
+ end
47
+ _sum(r) - _sum(l)
48
+ else
49
+ _sum(a)
50
+ end
34
51
  end
35
52
 
36
53
  def _sum(i)
@@ -41,8 +58,5 @@ class FenwickTree
41
58
  end
42
59
  res
43
60
  end
61
+ alias left_sum _sum
44
62
  end
45
-
46
- FeTree = FenwickTree
47
- Fetree = FenwickTree
48
- BinaryIndexedTree = FenwickTree