ac-library-rb 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f2e1122b67c3de38764556c098f3baca940daf337deae414b37ca57c0d23066
4
- data.tar.gz: a5623bda479b49cd40885aa202b64c3075b292db06c3f0b2fea6ba2882e8e281
3
+ metadata.gz: dc333b7ea588fedc3aaf0379408bb5cfa0cbe78ce78286375233e296ee687338
4
+ data.tar.gz: 8b22febe194ced2ce838d6c5c59316e813acb1d3835988981bcd8ee48512a460
5
5
  SHA512:
6
- metadata.gz: 5f38c20da10aa7b69cc140b8c79e7f3152271b77fe265f6ad8b93114a986b714b7b004cec5365477d6661192ed319da126868e8151ac00236633a5e5c6ac22a6
7
- data.tar.gz: ed0b8ff7db0eff11fdf751acba9b111488d14babb845c747fb7856888d600b34e5f53208b6aa2fdbddb9ad1001996040dafb6a240498d59a5517fd6d8dfa0229
6
+ metadata.gz: '09aae15824b338694ba75027deea63c5955e9056fb5af8ea3d382d0218fa6278ef8af2e9d281315ef45e01a4296e6b15688f221ea39ca03153a1799d7770cc7e'
7
+ data.tar.gz: db447beabc1e50f306a26a34128394e0c424d5291cb9df4b616bcadc3956a5acd90b6344fc80eaedadfa88efba96ee3918a622e582b8957c3b21be12f44b3636
data/.rubocop.yml CHANGED
@@ -91,6 +91,7 @@ Naming/FileName:
91
91
  - 'lib_lock/ac-library-rb.rb'
92
92
  Naming/AccessorMethodName:
93
93
  Exclude:
94
+ - 'lib/lazy_segtree.rb'
94
95
  - 'lib/modint.rb'
95
96
  Naming/MethodName:
96
97
  Exclude:
@@ -124,6 +125,7 @@ Style/GlobalVars:
124
125
  AutoCorrect: false
125
126
  Exclude:
126
127
  - 'lib/modint.rb'
128
+ - 'test/lazy_segtree_test.rb'
127
129
  Style/FrozenStringLiteralComment:
128
130
  Enabled: false
129
131
  Style/InverseMethods:
@@ -179,6 +181,7 @@ Style/SelfAssignment:
179
181
  Style/Semicolon:
180
182
  Exclude:
181
183
  - 'lib/lazy_segtree.rb'
184
+ - 'test/lazy_segtree_test.rb'
182
185
  Style/SlicingWithRange:
183
186
  Enabled: false
184
187
  Style/SpecialGlobalVars:
data/README.ja.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # ac-library-rb
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/ac-library-rb.svg)](https://badge.fury.io/rb/ac-library-rb)
4
+
3
5
  ac-library-rbは、AtCoder Library (ACL)のRuby版です。
4
6
 
5
7
  ACLの詳細は、以下をご覧ください.
@@ -114,12 +116,33 @@ ACL本家のレポジトリ名がac-libraryとハイフン区切りで、それ
114
116
 
115
117
  宣伝・バグ報告などしてもらえると嬉しいです。
116
118
 
119
+ ## ac-library-rbを開発したい方向けの情報
120
+
121
+ ### コーディングスタイル
122
+
123
+ Rubocop(Rubyのlintツール)の設定ファイル`.rubocop.yml`は、参考に置いています。
124
+ Rubocopのルールを守ることが必ずしもよくなかったり、ルールを守ることが難しかったりもするので、Rubocopの適用は必須ではないです。
125
+
126
+ 推奨スタイル
127
+ - インデントは、半角スペース2文字
128
+ - 行末の余計なスペースは削除
129
+
130
+ ### ディレクトリの説明
131
+
132
+ `lib`ディレクトリ内に各種のデータ構造などのライブラリがあります。
133
+ `lib_lock`は、Gem用にモジュール化させるため`lib`の内容をコピーする形でモジュール化させています。
134
+ `bin/lock_lib.rb`を実行することで、`lib`から`lib_lock`にモジュール化させる形でコピーします。
135
+ なお、`rake`コマンドでテストを実行させると、自動的に`require_relative "./bin/lock_lib.rb"`により、コピーが行われます。
136
+ このあたりはトリッキーで、予定は未定ですが、今後全てモジュール化される等に統一される可能性があります。
137
+
117
138
  ## その他の情報
118
139
 
119
140
  ### RubyのSlackのAtCoderチャンネル
120
141
 
121
142
  [ruby-jp](https://ruby-jp.github.io/) に"atcoder"というチャンネルがあります。
122
143
 
144
+ ここで、バグ報告などすると、競プロ詳しい人などが反応しやすいかもしれません。
145
+
123
146
  Slackに3000人、atcoderチャンネルに250人以上の登録者がいるので、お気軽に参加してください。
124
147
 
125
148
  ### 他言語のライブラリ
data/README.md CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  # ac-library-rb
9
9
 
10
+ [![Gem Version](https://badge.fury.io/rb/ac-library-rb.svg)](https://badge.fury.io/rb/ac-library-rb)
11
+
10
12
  ac-library-rb is a ruby port of AtCoder Library (ACL).
11
13
 
12
14
  See below for ACL.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- # require_relative "./bin/lock_lib.rb"
5
+ require_relative "./bin/lock_lib.rb" # for copy
6
6
  t.warning = false
7
7
  t.libs << "test"
8
8
  t.libs << "lib"
@@ -105,13 +105,29 @@ seg.range_apply(l, r, val)
105
105
 
106
106
  - `O(log n)`
107
107
 
108
- ### max_right.
108
+ ### max_right(l){ } -> Integer
109
109
 
110
- [TODO] Someone with some free time will write.
110
+ It applies binary search on the LazySegtree.
111
111
 
112
- ### min_left
112
+ **Constraints**
113
+
114
+ - `0 ≦ l ≦ n`
115
+
116
+ **Complexity**
117
+
118
+ - `O(log n)`
119
+
120
+ ### min_left(r){ } -> Integer
113
121
 
114
- [TODO] The code side is not implemented yet.
122
+ It applies binary search on the LazySegtree.
123
+
124
+ **Constraints**
125
+
126
+ - `0 ≦ r ≦ n`
127
+
128
+ **Complexity**
129
+
130
+ - `O(log n)`
115
131
 
116
132
  ## Verified
117
133
 
@@ -104,6 +104,14 @@ It returns `op(a[0], ..., a[n - 1])`.
104
104
  seg.max_right(l, &f)
105
105
  ```
106
106
 
107
+ **Constraints**
108
+
109
+ - `0 ≦ l ≦ n`
110
+
111
+ **Complexity**
112
+
113
+ - `O(log n)`
114
+
107
115
  It applies binary search on the segment tree.
108
116
 
109
117
  ### min_left(r, &f) -> Integer
@@ -114,6 +122,14 @@ seg.min_left(r, &f)
114
122
 
115
123
  It applies binary search on the segment tree.
116
124
 
125
+ **Constraints**
126
+
127
+ - `0 ≦ r ≦ n`
128
+
129
+ **Complexity**
130
+
131
+ - `O(log n)`
132
+
117
133
  ## Verified
118
134
 
119
135
  - [ALPC: J \- Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
@@ -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](ttps://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
  - 当ライブラリ
@@ -133,3 +168,10 @@ seg.range_apply(l, r, val)
133
168
  ### `ceil_pow2`ではなく、`bit_length`
134
169
 
135
170
  本家C++ライブラリは独自定義の`internal::ceil_pow2`関数を用いてますが、本ライブラリではRuby既存のメソッド`Integer#bit_length`を用いています。そちらの方が計測した結果、高速でした。
171
+
172
+ ## 問題点
173
+
174
+ ### ミュータブルな単位元
175
+
176
+ 本家ACL同様に、初期化の際に配列でも数値でもいいとなっている。
177
+ しかし、数値で要素数を指定した際に、ミュータブルなクラスでも同一オブジェクトで要素を作ってしまっている。
@@ -66,7 +66,7 @@ seg.get(pos)
66
66
  seg.prod(l, r)
67
67
  ```
68
68
 
69
- `op(a[l], ..., a[r - 1])` を返します。
69
+ `op(a[l], ..., a[r - 1])` を返します。引数は半開区間です。`l == r`のとき、単位元`e`を返します。
70
70
 
71
71
  **制約**
72
72
 
@@ -82,7 +82,7 @@ seg.prod(l, r)
82
82
  seg.all_prod
83
83
  ```
84
84
 
85
- `op(a[0], ..., a[n - 1])` を返します。
85
+ `op(a[0], ..., a[n - 1])` を返します。空のセグメントツリー、つまりサイズが0のとき、単位元`e`を返します。
86
86
 
87
87
  **計算量**
88
88
 
@@ -96,6 +96,10 @@ seg.max_right(l, &f)
96
96
 
97
97
  Segtree上で二分探索をします。
98
98
 
99
+ **制約** `0 ≦ l ≦ n`
100
+
101
+ **計算量** `O(log n)`
102
+
99
103
  ### min_left(r, &f) -> Integer
100
104
 
101
105
  ```ruby
@@ -104,11 +108,15 @@ seg.min_left(r, &f)
104
108
 
105
109
  Segtree上で二分探索をします。
106
110
 
111
+ **制約** `0 ≦ r ≦ n`
112
+
113
+ **計算量** `O(log n)`
114
+
107
115
  ## Verified
108
116
 
109
117
  - [ALPC: J \- Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
110
118
 
111
- - [F \- Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
119
+ - [ABC185: F \- Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
112
120
  - xorのセグメントツリーの基本的な典型問題です。FenwickTree(BIT)をxorに改造するだけでも解けます。
113
121
  - [ACコード(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): 通常のSegtree解。
114
122
  - [ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT)のxor改造版。
@@ -1,3 +1,3 @@
1
1
  module AcLibraryRb
2
- VERSION = "0.5.1".freeze
2
+ VERSION = "0.5.2".freeze
3
3
  end
data/lib/lazy_segtree.rb CHANGED
@@ -1,17 +1,21 @@
1
1
  # Segment tree with Lazy propagation
2
2
  class LazySegtree
3
- attr_reader :d, :lz
3
+ attr_reader :d, :lz, :e, :id
4
4
  attr_accessor :op, :mapping, :composition
5
5
 
6
- def initialize(v, e, id, op, mapping, composition)
7
- v = Array.new(v, e) if v.is_a?(Integer)
6
+ # new(v, op, e, mapping, composition, id)
7
+ # new(v, e, id, op, mapping, composition)
8
+ # new(v, e, id){ |x, y| }
9
+ def initialize(v, a1, a2, a3 = nil, a4 = nil, a5 = nil, &op_block)
10
+ if a1.is_a?(Proc)
11
+ @op, @e, @mapping, @composition, @id = a1, a2, a3, a4, a5
12
+ else
13
+ @e, @id, @op, @mapping, @composition = a1, a2, a3, a4, a5
14
+ @op ||= op_block
15
+ end
16
+ v = Array.new(v, @e) if v.is_a?(Integer)
8
17
 
9
18
  @n = v.size
10
- @e = e
11
- @id = id
12
- @op = op
13
- @mapping = mapping
14
- @composition = composition
15
19
 
16
20
  @log = (@n - 1).bit_length
17
21
  @size = 1 << @log
@@ -22,18 +26,28 @@ class LazySegtree
22
26
  (@size - 1).downto(1) { |i| update(i) }
23
27
  end
24
28
 
29
+ def set_mapping(&mapping)
30
+ @mapping = mapping
31
+ end
32
+
33
+ def set_composition(&composition)
34
+ @composition = composition
35
+ end
36
+
25
37
  def set(pos, x)
26
38
  pos += @size
27
39
  @log.downto(1) { |i| push(pos >> i) }
28
40
  @d[pos] = x
29
41
  1.upto(@log) { |i| update(pos >> i) }
30
42
  end
43
+ alias []= set
31
44
 
32
45
  def get(pos)
33
46
  pos += @size
34
47
  @log.downto(1) { |i| push(pos >> i) }
35
48
  @d[pos]
36
49
  end
50
+ alias [] get
37
51
 
38
52
  def prod(l, r)
39
53
  return @e if l == r
@@ -68,7 +82,11 @@ class LazySegtree
68
82
  @d[1]
69
83
  end
70
84
 
71
- def apply(pos, f)
85
+ # apply(pos, f)
86
+ # apply(l, r, f) -> range_apply(l, r, f)
87
+ def apply(pos, f, fr = nil)
88
+ return range_apply(pos, f, fr) if fr
89
+
72
90
  pos += @size
73
91
  @log.downto(1) { |i| push(pos >> i) }
74
92
  @d[pos] = @mapping.call(f, @d[pos])
@@ -132,6 +150,35 @@ class LazySegtree
132
150
  @n
133
151
  end
134
152
 
153
+ def min_left(r, &g)
154
+ return 0 if r == 0
155
+
156
+ r += @size
157
+ @log.downto(1) { |i| push((r - 1) >> i) }
158
+ sm = @e
159
+
160
+ loop do
161
+ r -= 1
162
+ while r > 1 && r.odd?
163
+ r /= 2
164
+ end
165
+ unless g.call(@op.call(@d[r], sm))
166
+ while r < @size
167
+ push(r)
168
+ r = r * 2 + 1
169
+ if g.call(@op.call(@d[r], sm))
170
+ sm = @op.call(@d[r], sm)
171
+ r -= 1
172
+ end
173
+ end
174
+ return r + 1 - @size
175
+ end
176
+ sm = @op.call(@d[r], sm)
177
+ break if (r & -r) == r
178
+ end
179
+ 0
180
+ end
181
+
135
182
  def update(k)
136
183
  @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
137
184
  end
data/lib/segtree.rb CHANGED
@@ -2,21 +2,25 @@
2
2
  class Segtree
3
3
  attr_reader :d, :op, :n, :leaf_size, :log
4
4
 
5
- def initialize(arg = 0, e, &block)
6
- case arg
7
- when Integer
8
- v = Array.new(arg) { e }
9
- when Array
10
- v = arg
5
+ # new(e){ |x, y| }
6
+ # new(v, e){ |x, y| }
7
+ # new(v, op, e)
8
+ def initialize(a0, a1 = nil, a2 = nil, &block)
9
+ if a1.nil?
10
+ @e, @op = a0, proc(&block)
11
+ v = []
12
+ elsif a2.nil?
13
+ @e, @op = a1, proc(&block)
14
+ v = (a0.is_a?(Array) ? a0 : [@e] * a0)
15
+ else
16
+ @op, @e = a1, a2
17
+ v = (a0.is_a?(Array) ? a0 : [@e] * a0)
11
18
  end
12
19
 
13
- @e = e
14
- @op = proc(&block)
15
-
16
20
  @n = v.size
17
21
  @log = (@n - 1).bit_length
18
22
  @leaf_size = 1 << @log
19
- @d = Array.new(@leaf_size * 2) { e }
23
+ @d = Array.new(@leaf_size * 2, @e)
20
24
  v.each_with_index { |v_i, i| @d[@leaf_size + i] = v_i }
21
25
  (@leaf_size - 1).downto(1) { |i| update(i) }
22
26
  end
@@ -26,10 +30,12 @@ class Segtree
26
30
  @d[q] = x
27
31
  1.upto(@log) { |i| update(q >> i) }
28
32
  end
33
+ alias []= set
29
34
 
30
35
  def get(pos)
31
36
  @d[@leaf_size + pos]
32
37
  end
38
+ alias [] get
33
39
 
34
40
  def prod(l, r)
35
41
  return @e if l == r
@@ -1,18 +1,22 @@
1
1
  module AcLibraryRb
2
2
  # Segment tree with Lazy propagation
3
3
  class LazySegtree
4
- attr_reader :d, :lz
4
+ attr_reader :d, :lz, :e, :id
5
5
  attr_accessor :op, :mapping, :composition
6
6
 
7
- def initialize(v, e, id, op, mapping, composition)
8
- v = Array.new(v, e) if v.is_a?(Integer)
7
+ # new(v, op, e, mapping, composition, id)
8
+ # new(v, e, id, op, mapping, composition)
9
+ # new(v, e, id){ |x, y| }
10
+ def initialize(v, a1, a2, a3 = nil, a4 = nil, a5 = nil, &op_block)
11
+ if a1.is_a?(Proc)
12
+ @op, @e, @mapping, @composition, @id = a1, a2, a3, a4, a5
13
+ else
14
+ @e, @id, @op, @mapping, @composition = a1, a2, a3, a4, a5
15
+ @op ||= op_block
16
+ end
17
+ v = Array.new(v, @e) if v.is_a?(Integer)
9
18
 
10
19
  @n = v.size
11
- @e = e
12
- @id = id
13
- @op = op
14
- @mapping = mapping
15
- @composition = composition
16
20
 
17
21
  @log = (@n - 1).bit_length
18
22
  @size = 1 << @log
@@ -23,18 +27,28 @@ module AcLibraryRb
23
27
  (@size - 1).downto(1) { |i| update(i) }
24
28
  end
25
29
 
30
+ def set_mapping(&mapping)
31
+ @mapping = mapping
32
+ end
33
+
34
+ def set_composition(&composition)
35
+ @composition = composition
36
+ end
37
+
26
38
  def set(pos, x)
27
39
  pos += @size
28
40
  @log.downto(1) { |i| push(pos >> i) }
29
41
  @d[pos] = x
30
42
  1.upto(@log) { |i| update(pos >> i) }
31
43
  end
44
+ alias []= set
32
45
 
33
46
  def get(pos)
34
47
  pos += @size
35
48
  @log.downto(1) { |i| push(pos >> i) }
36
49
  @d[pos]
37
50
  end
51
+ alias [] get
38
52
 
39
53
  def prod(l, r)
40
54
  return @e if l == r
@@ -69,7 +83,11 @@ module AcLibraryRb
69
83
  @d[1]
70
84
  end
71
85
 
72
- def apply(pos, f)
86
+ # apply(pos, f)
87
+ # apply(l, r, f) -> range_apply(l, r, f)
88
+ def apply(pos, f, fr = nil)
89
+ return range_apply(pos, f, fr) if fr
90
+
73
91
  pos += @size
74
92
  @log.downto(1) { |i| push(pos >> i) }
75
93
  @d[pos] = @mapping.call(f, @d[pos])
@@ -133,6 +151,35 @@ module AcLibraryRb
133
151
  @n
134
152
  end
135
153
 
154
+ def min_left(r, &g)
155
+ return 0 if r == 0
156
+
157
+ r += @size
158
+ @log.downto(1) { |i| push((r - 1) >> i) }
159
+ sm = @e
160
+
161
+ loop do
162
+ r -= 1
163
+ while r > 1 && r.odd?
164
+ r /= 2
165
+ end
166
+ unless g.call(@op.call(@d[r], sm))
167
+ while r < @size
168
+ push(r)
169
+ r = r * 2 + 1
170
+ if g.call(@op.call(@d[r], sm))
171
+ sm = @op.call(@d[r], sm)
172
+ r -= 1
173
+ end
174
+ end
175
+ return r + 1 - @size
176
+ end
177
+ sm = @op.call(@d[r], sm)
178
+ break if (r & -r) == r
179
+ end
180
+ 0
181
+ end
182
+
136
183
  def update(k)
137
184
  @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
138
185
  end
@@ -3,21 +3,25 @@ module AcLibraryRb
3
3
  class Segtree
4
4
  attr_reader :d, :op, :n, :leaf_size, :log
5
5
 
6
- def initialize(arg = 0, e, &block)
7
- case arg
8
- when Integer
9
- v = Array.new(arg) { e }
10
- when Array
11
- v = arg
6
+ # new(e){ |x, y| }
7
+ # new(v, e){ |x, y| }
8
+ # new(v, op, e)
9
+ def initialize(a0, a1 = nil, a2 = nil, &block)
10
+ if a1.nil?
11
+ @e, @op = a0, proc(&block)
12
+ v = []
13
+ elsif a2.nil?
14
+ @e, @op = a1, proc(&block)
15
+ v = (a0.is_a?(Array) ? a0 : [@e] * a0)
16
+ else
17
+ @op, @e = a1, a2
18
+ v = (a0.is_a?(Array) ? a0 : [@e] * a0)
12
19
  end
13
20
 
14
- @e = e
15
- @op = proc(&block)
16
-
17
21
  @n = v.size
18
22
  @log = (@n - 1).bit_length
19
23
  @leaf_size = 1 << @log
20
- @d = Array.new(@leaf_size * 2) { e }
24
+ @d = Array.new(@leaf_size * 2, @e)
21
25
  v.each_with_index { |v_i, i| @d[@leaf_size + i] = v_i }
22
26
  (@leaf_size - 1).downto(1) { |i| update(i) }
23
27
  end
@@ -27,10 +31,12 @@ module AcLibraryRb
27
31
  @d[q] = x
28
32
  1.upto(@log) { |i| update(q >> i) }
29
33
  end
34
+ alias []= set
30
35
 
31
36
  def get(pos)
32
37
  @d[@leaf_size + pos]
33
38
  end
39
+ alias [] get
34
40
 
35
41
  def prod(l, r)
36
42
  return @e if l == r
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ac-library-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - universato
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-17 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest