ac-library-rb 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/README.ja.md +102 -4
- data/README.md +73 -1
- data/Rakefile +2 -1
- data/ac-library-rb.gemspec +3 -2
- data/bin/lock_lib.rb +13 -7
- data/document_en/dsu.md +2 -2
- data/document_en/lazy_segtree.md +20 -4
- data/document_en/max_flow.md +1 -1
- data/document_en/min_cost_flow.md +1 -1
- data/document_en/segtree.md +36 -3
- data/document_en/two_sat.md +1 -1
- data/document_ja/dsu.md +1 -3
- data/document_ja/lazy_segtree.md +63 -19
- data/document_ja/max_flow.md +1 -1
- data/document_ja/min_cost_flow.md +1 -1
- data/document_ja/scc.md +4 -3
- data/document_ja/segtree.md +49 -8
- data/document_ja/two_sat.md +1 -1
- data/lib/ac-library-rb/version.rb +1 -1
- data/lib/convolution.rb +21 -0
- data/lib/core_ext/all.rb +11 -0
- data/lib/dsu.rb +9 -6
- data/lib/fenwick_tree.rb +22 -8
- data/lib/floor_sum.rb +33 -10
- data/lib/lazy_segtree.rb +83 -10
- data/lib/max_flow.rb +10 -4
- data/lib/min_cost_flow.rb +13 -7
- data/lib/modint.rb +3 -1
- data/lib/scc.rb +21 -13
- data/lib/segtree.rb +38 -26
- data/lib/suffix_array.rb +8 -8
- data/lib/two_sat.rb +5 -3
- data/lib_lock/ac-library-rb.rb +2 -0
- data/lib_lock/ac-library-rb/convolution.rb +21 -0
- data/lib_lock/ac-library-rb/core_ext/all.rb +11 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +3 -3
- data/lib_lock/ac-library-rb/dsu.rb +9 -6
- data/lib_lock/ac-library-rb/fenwick_tree.rb +22 -8
- data/lib_lock/ac-library-rb/floor_sum.rb +33 -10
- data/lib_lock/ac-library-rb/lazy_segtree.rb +83 -10
- data/lib_lock/ac-library-rb/max_flow.rb +10 -4
- data/lib_lock/ac-library-rb/min_cost_flow.rb +13 -7
- data/lib_lock/ac-library-rb/modint.rb +3 -1
- data/lib_lock/ac-library-rb/scc.rb +21 -13
- data/lib_lock/ac-library-rb/segtree.rb +38 -26
- data/lib_lock/ac-library-rb/suffix_array.rb +8 -8
- data/lib_lock/ac-library-rb/two_sat.rb +5 -3
- metadata +20 -4
data/document_en/two_sat.md
CHANGED
data/document_ja/dsu.md
CHANGED
@@ -30,7 +30,7 @@ p d.size(2) # => 2
|
|
30
30
|
|
31
31
|
## 特異メソッド
|
32
32
|
|
33
|
-
### new(n
|
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
|
|
data/document_ja/lazy_segtree.md
CHANGED
@@ -8,10 +8,10 @@
|
|
8
8
|
|
9
9
|
## 特異メソッド
|
10
10
|
|
11
|
-
### new(v, e, id
|
11
|
+
### new(v, e, id){ }
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
seg = LazySegtree.new(v, e, id
|
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
|
-
|
94
|
+
1. `a[p] = f(a[p])`
|
95
|
+
2. 半開区間`i = l..r`について`a[i] = f(a[i])`
|
79
96
|
|
80
|
-
**制約**
|
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
|
-
|
118
|
+
LazySegtree上で、二分探索をします。
|
97
119
|
|
98
|
-
|
120
|
+
**制約** `0 ≦ l ≦ n`
|
99
121
|
|
100
|
-
|
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
|
-
|
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
|
-
- [
|
124
|
-
- [
|
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
|
-
- [
|
127
|
-
- [
|
128
|
-
- [ACLPC: K–Range Affine Range Sumの解説
|
129
|
-
- [
|
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
|
+
しかし、数値で要素数を指定した際に、ミュータブルなクラスでも同一オブジェクトで要素を作ってしまっている。
|
data/document_ja/max_flow.md
CHANGED
data/document_ja/scc.md
CHANGED
@@ -6,7 +6,7 @@ Strongly Connected Components
|
|
6
6
|
|
7
7
|
## 特異メソッド
|
8
8
|
|
9
|
-
### new(n
|
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
|
|
data/document_ja/segtree.md
CHANGED
@@ -4,7 +4,8 @@
|
|
4
4
|
|
5
5
|
## 特異メソッド
|
6
6
|
|
7
|
-
### new(arg, e,
|
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
|
-
- [
|
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
|
|
data/document_ja/two_sat.md
CHANGED
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
|
data/lib/core_ext/all.rb
ADDED
data/lib/dsu.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# Disjoint Set Union
|
2
2
|
class DSU
|
3
|
-
def initialize(n
|
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
|
-
|
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
|
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 =
|
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
|
-
|
33
|
-
|
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
|