ac-library-rb 0.5.4 → 0.6.0

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: 7eb404ec2eab941e961da5a9cc0e19b87858a33101c791750a2e33d61781f8b8
4
- data.tar.gz: a341ee2e478add1f3e611071213911dd919e7229ca3cc8cc9c19880e3e471467
3
+ metadata.gz: f191f90563fea038c7181e2bf9d13e1dc8caa0e816a364176e46b67c8d63f471
4
+ data.tar.gz: c89db082816046146cb60faa3747e046877394bfff776a3defe8063fb2d1c390
5
5
  SHA512:
6
- metadata.gz: 053064e9c40fe91e306a7695906bec15ef8752c3ddfa54f7954bf83f5954a626370f9390034f0777c0e403460f7ed650707a89be6a02d88c49cb52cdb0da5ffb
7
- data.tar.gz: 910dd3b9d493efba69cfe458a41a82c28ba4b5dde013521f56b29fbe7f3737d7d82fd50424b205c98683f0691da843de6ffc3ec58dd5cdf75e7d7ed1d94f1185
6
+ metadata.gz: '0114099d09f9566741d84ed2b5e43427b62592bb8b2a6b90d25b9f68288d2a387f34899351d18a7b3e0c93ec72af9cae4aac2f1d38f5fe517e30ec850e33429e'
7
+ data.tar.gz: cdb1eac1808855f86c00c991b4c66ae3489035420ef0fdb8c88915712ace8faa5db02da074a78734e0c4235058ac1e2a62a0fc9cc0523e6c85aff4617b47ae39
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "minitest"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "simplecov"
23
24
 
24
25
  # Specify which files should be added to the gem when it is released.
25
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
data/bin/lock_lib.rb CHANGED
@@ -17,7 +17,7 @@ Dir.glob(lib_path) do |file|
17
17
  end
18
18
 
19
19
  # copy library from `lib/core_ext` to `lib_lock/ac-library-rb/core_ext`
20
- ac_library_rb_classes = %w[ModInt]
20
+ ac_library_rb_classes = %w[ModInt FenwickTree PriorityQueue]
21
21
  replaces = ac_library_rb_classes.to_h{ |cls| ["#{cls}.new", "AcLibraryRb::#{cls}.new"] }
22
22
  pattern = Regexp.new(replaces.keys.join('|'))
23
23
 
data/document_en/dsu.md CHANGED
@@ -27,7 +27,7 @@ p d.size(2) # => 2
27
27
 
28
28
  ## Class Method
29
29
 
30
- ### new(n = 0) -> DSU
30
+ ### new(n) -> DSU
31
31
 
32
32
  ```rb
33
33
  d = DSU.new(n)
@@ -41,7 +41,7 @@ It creates an undirected graph with `n` vertices and `0` edges.
41
41
 
42
42
  **alias**
43
43
 
44
- - `DSU`, `DisjointSetUnion`, `UnionFind`, `UnionFindTree`
44
+ - `DSU`, `UnionFind`
45
45
 
46
46
  ## Instance Methods
47
47
 
@@ -5,7 +5,7 @@ Library for solving [Maximum flow problem](https://en.wikipedia.org/wiki/Maximum
5
5
 
6
6
  ## Class Methods.
7
7
 
8
- ### new(n = 0) -> MaxFlow
8
+ ### new(n) -> MaxFlow
9
9
 
10
10
  ```ruby
11
11
  graph = Maxflow.new(10)
@@ -4,7 +4,7 @@ It solves [Minimum\-cost flow problem](https://en.wikipedia.org/wiki/Minimum-cos
4
4
 
5
5
  ## Class Methods.
6
6
 
7
- ### new(n = 0) -> MinCostFlow
7
+ ### new(n) -> MinCostFlow
8
8
 
9
9
  ```ruby
10
10
  graph = MinCostFlow.new(10)
@@ -4,7 +4,8 @@ Segment Tree
4
4
 
5
5
  ## Class Methods
6
6
 
7
- ### new(n, e, &op) -> Segtree
7
+ ### new(n, e){ |x, y| ... } -> Segtree
8
+ ### new(n, op, e) -> Segtree
8
9
 
9
10
  ```rb
10
11
  seg = Segtree.new(n, e) { |x, y| ... }
@@ -15,7 +16,9 @@ It creates an array `a` of length `n`. All the elements are initialized to `e`.
15
16
  - `block`: returns `op(x, y)`
16
17
  - `e`: identity element.
17
18
 
18
- ### new(ary, e, &op) -> Segtree
19
+
20
+ ### new(ary, e){ |x, y| ... } -> Segtree
21
+ ### new(ary, op, e) -> Segtree
19
22
 
20
23
  ```rb
21
24
  seg = Segtree.new(ary, e) { |x, y| ... }
@@ -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
 
@@ -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| ... }
@@ -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.4".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,13 +1,13 @@
1
1
  # Disjoint Set Union
2
2
  class DSU
3
- def initialize(n = 0)
3
+ def initialize(n)
4
4
  @n = n
5
5
  @parent_or_size = Array.new(n, -1)
6
6
  # root node: -1 * component size
7
7
  # otherwise: parent
8
8
  end
9
9
 
10
- attr_accessor :parent_or_size
10
+ attr_reader :parent_or_size, :n
11
11
 
12
12
  def merge(a, b)
13
13
  x = leader(a)
@@ -27,7 +27,7 @@ class DSU
27
27
 
28
28
  def leader(a)
29
29
  unless 0 <= a && a < @n
30
- raise ArgumentError.new, "#{a} is out of range 0 <= arg < size"
30
+ raise ArgumentError.new, "#{a} is out of range (0...#{@n})"
31
31
  end
32
32
 
33
33
  @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
@@ -44,6 +44,4 @@ class DSU
44
44
  end
45
45
  end
46
46
 
47
- UnionFind = DSU
48
- UnionFindTree = DSU
49
- 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)
@@ -43,7 +60,3 @@ class FenwickTree
43
60
  end
44
61
  alias left_sum _sum
45
62
  end
46
-
47
- FeTree = FenwickTree
48
- Fetree = FenwickTree
49
- BinaryIndexedTree = FenwickTree
data/lib/lazy_segtree.rb CHANGED
@@ -49,7 +49,18 @@ class LazySegtree
49
49
  end
50
50
  alias [] get
51
51
 
52
- def prod(l, r)
52
+ def prod(l, r = nil)
53
+ if r.nil? # if 1st argument l is Range
54
+ if r = l.end
55
+ r += @n if r < 0
56
+ r += 1 unless l.exclude_end?
57
+ else
58
+ r = @n
59
+ end
60
+ l = l.begin
61
+ l += @n if l < 0
62
+ end
63
+
53
64
  return @e if l == r
54
65
 
55
66
  l += @size
@@ -83,9 +94,22 @@ class LazySegtree
83
94
  end
84
95
 
85
96
  # apply(pos, f)
86
- # apply(l, r, f) -> range_apply(l, r, f)
97
+ # apply(l, r, f) -> range_apply(l, r, f)
98
+ # apply(l...r, f) -> range_apply(l, r, f) ... [Experimental]
87
99
  def apply(pos, f, fr = nil)
88
- return range_apply(pos, f, fr) if fr
100
+ if fr
101
+ return range_apply(pos, f, fr)
102
+ elsif pos.is_a?(Range)
103
+ l = pos.begin
104
+ l += @n if l < 0
105
+ if r = pos.end
106
+ r += @n if r < 0
107
+ r += 1 unless pos.exclude_end?
108
+ else
109
+ r = @n
110
+ end
111
+ return range_apply(l, r, f)
112
+ end
89
113
 
90
114
  pos += @size
91
115
  @log.downto(1) { |i| push(pos >> i) }
@@ -194,3 +218,5 @@ class LazySegtree
194
218
  @lz[k] = @id
195
219
  end
196
220
  end
221
+
222
+ LazySegTree = LazySegtree
data/lib/max_flow.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # MaxFlowGraph
2
2
  class MaxFlow
3
- def initialize(n = 0)
3
+ def initialize(n)
4
4
  @n = n
5
5
  @pos = []
6
6
  @g = Array.new(n) { [] }
@@ -20,6 +20,15 @@ class MaxFlow
20
20
  edge_number
21
21
  end
22
22
 
23
+ def add_edges(edges)
24
+ edges.each{ |from, to, cap| add_edge(from, to, cap) }
25
+ self
26
+ end
27
+
28
+ def add(x, to = nil, cap = nil)
29
+ cap ? add_edge(x, to, cap) : add_edges(x)
30
+ end
31
+
23
32
  def push(edge)
24
33
  add_edge(*edge)
25
34
  end
@@ -132,6 +141,3 @@ class MaxFlow
132
141
  res
133
142
  end
134
143
  end
135
-
136
- MaxFlowGraph = MaxFlow
137
- MFGraph = MaxFlow
data/lib/min_cost_flow.rb CHANGED
@@ -11,7 +11,7 @@ class MinCostFlow
11
11
  @g_cost = Array.new(n) { [] }
12
12
  @pv = Array.new(n)
13
13
  @pe = Array.new(n)
14
- @dual = Array.new(n) { 0 }
14
+ @dual = Array.new(n, 0)
15
15
  end
16
16
 
17
17
  def add_edge(from, to, cap, cost)
@@ -36,6 +36,15 @@ class MinCostFlow
36
36
  edge_number
37
37
  end
38
38
 
39
+ def add_edges(edges)
40
+ edges.each{ |from, to, cap, cost| add_edge(from, to, cap, cost) }
41
+ self
42
+ end
43
+
44
+ def add(x, to = nil, cap = nil, cost = nil)
45
+ cost ? add_edge(x, to, cap, cost) : add_edges(x)
46
+ end
47
+
39
48
  def get_edge(i)
40
49
  from, id = @pos[i]
41
50
  to = @g_to[from][id]
@@ -138,6 +147,3 @@ class MinCostFlow
138
147
  end
139
148
  alias min_cost_slop slope
140
149
  end
141
-
142
- MCF = MinCostFlow
143
- MCFGraph = MinCostFlow
data/lib/scc.rb CHANGED
@@ -1,18 +1,31 @@
1
1
  # Strongly Connected Components
2
2
  class SCC
3
3
  # initialize graph with n vertices
4
- def initialize(n = 0)
5
- @n, @edges = n, []
4
+ def initialize(n)
5
+ @n = n
6
+ @edges = []
6
7
  end
7
8
 
8
9
  # add directed edge
9
10
  def add_edge(from, to)
10
- raise "invalid params" unless (0...@n).include? from and (0...@n).include? to
11
+ unless 0 <= from && from < @n and 0 <= to && to < @n
12
+ msg = "Wrong params: from=#{from} and to=#{to} must be in 0...#{@n}"
13
+ raise ArgumentError.new(msg)
14
+ end
11
15
 
12
16
  @edges << [from, to]
13
17
  self
14
18
  end
15
19
 
20
+ def add_edges(edges)
21
+ edges.each{ |from, to| add_edge(from, to) }
22
+ self
23
+ end
24
+
25
+ def add(x, to = nil)
26
+ to ? add_edge(x, to) : add_edges(x)
27
+ end
28
+
16
29
  # returns list of strongly connected components
17
30
  # the components are sorted in topological order
18
31
  # O(@n + @edges.size)
@@ -58,7 +71,8 @@ class SCC
58
71
  end
59
72
 
60
73
  def csr
61
- start, elist = [0] * (@n + 1), [nil] * @edges.size
74
+ start = [0] * (@n + 1)
75
+ elist = [nil] * @edges.size
62
76
  @edges.each { |(i, _)| start[i + 1] += 1 }
63
77
  @n.times { |i| start[i + 1] += start[i] }
64
78
  counter = start.dup
@@ -69,8 +83,3 @@ class SCC
69
83
  [start, elist]
70
84
  end
71
85
  end
72
-
73
- # class alias
74
- StronglyConnectedComponents = SCC
75
- SCCGraph = SCC
76
- SCCG = SCC
data/lib/segtree.rb CHANGED
@@ -2,14 +2,10 @@
2
2
  class Segtree
3
3
  attr_reader :d, :op, :n, :leaf_size, :log
4
4
 
5
- # new(e){ |x, y| }
6
5
  # new(v, e){ |x, y| }
7
6
  # 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?
7
+ def initialize(a0, a1, a2 = nil, &block)
8
+ if a2.nil?
13
9
  @e, @op = a1, proc(&block)
14
10
  v = (a0.is_a?(Array) ? a0 : [@e] * a0)
15
11
  else
@@ -37,7 +33,18 @@ class Segtree
37
33
  end
38
34
  alias [] get
39
35
 
40
- def prod(l, r)
36
+ def prod(l, r = nil)
37
+ if r.nil? # if 1st argument l is Range
38
+ if r = l.end
39
+ r += @n if r < 0
40
+ r += 1 unless l.exclude_end?
41
+ else
42
+ r = @n
43
+ end
44
+ l = l.begin
45
+ l += @n if l < 0
46
+ end
47
+
41
48
  return @e if l == r
42
49
 
43
50
  sml = @e
@@ -129,7 +136,7 @@ class Segtree
129
136
 
130
137
  # def inspect # for debug
131
138
  # t = 0
132
- # res = "SegmentTree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
139
+ # res = "Segtree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
133
140
  # a = @d[1, @d.size - 1]
134
141
  # a.each_with_index do |e, i|
135
142
  # res << e.to_s << ' '
@@ -142,5 +149,4 @@ class Segtree
142
149
  # end
143
150
  end
144
151
 
145
- SegTree = Segtree
146
- SegmentTree = Segtree
152
+ SegTree = Segtree
data/lib/two_sat.rb CHANGED
@@ -3,16 +3,18 @@ require_relative './scc.rb'
3
3
  # TwoSAT
4
4
  # Reference: https://github.com/atcoder/ac-library/blob/master/atcoder/twosat.hpp
5
5
  class TwoSAT
6
- def initialize(n = 0)
6
+ def initialize(n)
7
7
  @n = n
8
8
  @answer = Array.new(n)
9
- @scc = SCCGraph.new(2 * n)
9
+ @scc = SCC.new(2 * n)
10
10
  end
11
11
 
12
12
  attr_reader :answer
13
13
 
14
14
  def add_clause(i, f, j, g)
15
- raise RangeError unless (0...@n).cover?(i) && (0...@n).cover?(j)
15
+ unless 0 <= i && i < @n and 0 <= j && j < @n
16
+ raise RangeError.new
17
+ end
16
18
 
17
19
  @scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0))
18
20
  @scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0))
@@ -2,6 +2,8 @@ module AcLibraryRb
2
2
  end
3
3
  include AcLibraryRb
4
4
 
5
+ require_relative './lib_lock/ac-library-rb/all.rb'
6
+
5
7
  require_relative './ac-library-rb/convolution'
6
8
  require_relative './ac-library-rb/crt'
7
9
  require_relative './ac-library-rb/dsu'
@@ -123,4 +123,25 @@ module AcLibraryRb
123
123
 
124
124
  private :batterfly, :batterfly_inv, :bsf, :calc_primitive_root
125
125
  end
126
+
127
+ # [EXPERIMENTAL]
128
+ def convolution(a, b, mod: 998244353, k: 35, z: 99)
129
+ n = a.size
130
+ m = b.size
131
+ return [] if n == 0 || m == 0
132
+
133
+ raise ArgumentError if a.min < 0 || b.min < 0
134
+
135
+ format = "%0#{k}x" # "%024x"
136
+ sa = ""
137
+ sb = ""
138
+ a.each{ |x| sa << (format % x) }
139
+ b.each{ |x| sb << (format % x) }
140
+
141
+ zero = '0'
142
+ s = zero * z + ("%x" % (sa.hex * sb.hex))
143
+ i = -(n + m - 1) * k - 1
144
+
145
+ Array.new(n + m - 1){ (s[i + 1..i += k] || zero).hex % mod }
146
+ end
126
147
  end
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def to_fenwick_tree
3
+ AcLibraryRb::FenwickTree.new(self)
4
+ end
5
+ alias to_fetree to_fenwick_tree
6
+
7
+ def to_priority_queue
8
+ AcLibraryRb::PriorityQueue.new(self)
9
+ end
10
+ alias to_pq to_priority_queue
11
+ end
@@ -1,14 +1,14 @@
1
1
  module AcLibraryRb
2
2
  # Disjoint Set Union
3
3
  class DSU
4
- def initialize(n = 0)
4
+ def initialize(n)
5
5
  @n = n
6
6
  @parent_or_size = Array.new(n, -1)
7
7
  # root node: -1 * component size
8
8
  # otherwise: parent
9
9
  end
10
10
 
11
- attr_accessor :parent_or_size
11
+ attr_reader :parent_or_size, :n
12
12
 
13
13
  def merge(a, b)
14
14
  x = leader(a)
@@ -28,7 +28,7 @@ module AcLibraryRb
28
28
 
29
29
  def leader(a)
30
30
  unless 0 <= a && a < @n
31
- raise ArgumentError.new, "#{a} is out of range 0 <= arg < size"
31
+ raise ArgumentError.new, "#{a} is out of range (0...#{@n})"
32
32
  end
33
33
 
34
34
  @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
@@ -45,7 +45,5 @@ module AcLibraryRb
45
45
  end
46
46
  end
47
47
 
48
- UnionFind = DSU
49
- UnionFindTree = DSU
50
- DisjointSetUnion = DSU
48
+ UnionFind = DSU
51
49
  end
@@ -3,7 +3,7 @@ module AcLibraryRb
3
3
  class FenwickTree
4
4
  attr_reader :data, :size
5
5
 
6
- def initialize(arg = 0)
6
+ def initialize(arg = nil)
7
7
  case arg
8
8
  when Array
9
9
  @size = arg.size
@@ -18,7 +18,7 @@ module AcLibraryRb
18
18
  @size = arg
19
19
  @data = Array.new(@size + 1, 0)
20
20
  else
21
- raise ArgumentError
21
+ raise ArgumentError.new("wrong argument. type is Array or Integer")
22
22
  end
23
23
  end
24
24
 
@@ -30,8 +30,25 @@ module AcLibraryRb
30
30
  end
31
31
  end
32
32
 
33
- def sum(l, r)
34
- _sum(r) - _sum(l)
33
+ # .sum(l, r) # [l, r) <- Original
34
+ # .sum(r) # [0, r) <- [Experimental]
35
+ # .sum(l..r) # [l, r] <- [Experimental]
36
+ def sum(a, b = nil)
37
+ if b
38
+ _sum(b) - _sum(a)
39
+ elsif a.is_a?(Range)
40
+ l = a.begin
41
+ l += @size if l < 0
42
+ if r = a.end
43
+ r += @size if r < 0
44
+ r += 1 unless a.exclude_end?
45
+ else
46
+ r = @size
47
+ end
48
+ _sum(r) - _sum(l)
49
+ else
50
+ _sum(a)
51
+ end
35
52
  end
36
53
 
37
54
  def _sum(i)
@@ -44,8 +61,4 @@ module AcLibraryRb
44
61
  end
45
62
  alias left_sum _sum
46
63
  end
47
-
48
- FeTree = FenwickTree
49
- Fetree = FenwickTree
50
- BinaryIndexedTree = FenwickTree
51
64
  end
@@ -50,7 +50,18 @@ module AcLibraryRb
50
50
  end
51
51
  alias [] get
52
52
 
53
- def prod(l, r)
53
+ def prod(l, r = nil)
54
+ if r.nil? # if 1st argument l is Range
55
+ if r = l.end
56
+ r += @n if r < 0
57
+ r += 1 unless l.exclude_end?
58
+ else
59
+ r = @n
60
+ end
61
+ l = l.begin
62
+ l += @n if l < 0
63
+ end
64
+
54
65
  return @e if l == r
55
66
 
56
67
  l += @size
@@ -84,9 +95,22 @@ module AcLibraryRb
84
95
  end
85
96
 
86
97
  # apply(pos, f)
87
- # apply(l, r, f) -> range_apply(l, r, f)
98
+ # apply(l, r, f) -> range_apply(l, r, f)
99
+ # apply(l...r, f) -> range_apply(l, r, f) ... [Experimental]
88
100
  def apply(pos, f, fr = nil)
89
- return range_apply(pos, f, fr) if fr
101
+ if fr
102
+ return range_apply(pos, f, fr)
103
+ elsif pos.is_a?(Range)
104
+ l = pos.begin
105
+ l += @n if l < 0
106
+ if r = pos.end
107
+ r += @n if r < 0
108
+ r += 1 unless pos.exclude_end?
109
+ else
110
+ r = @n
111
+ end
112
+ return range_apply(l, r, f)
113
+ end
90
114
 
91
115
  pos += @size
92
116
  @log.downto(1) { |i| push(pos >> i) }
@@ -195,4 +219,6 @@ module AcLibraryRb
195
219
  @lz[k] = @id
196
220
  end
197
221
  end
222
+
223
+ LazySegTree = LazySegtree
198
224
  end
@@ -1,7 +1,7 @@
1
1
  module AcLibraryRb
2
2
  # MaxFlowGraph
3
3
  class MaxFlow
4
- def initialize(n = 0)
4
+ def initialize(n)
5
5
  @n = n
6
6
  @pos = []
7
7
  @g = Array.new(n) { [] }
@@ -21,6 +21,15 @@ module AcLibraryRb
21
21
  edge_number
22
22
  end
23
23
 
24
+ def add_edges(edges)
25
+ edges.each{ |from, to, cap| add_edge(from, to, cap) }
26
+ self
27
+ end
28
+
29
+ def add(x, to = nil, cap = nil)
30
+ cap ? add_edge(x, to, cap) : add_edges(x)
31
+ end
32
+
24
33
  def push(edge)
25
34
  add_edge(*edge)
26
35
  end
@@ -133,7 +142,4 @@ module AcLibraryRb
133
142
  res
134
143
  end
135
144
  end
136
-
137
- MaxFlowGraph = MaxFlow
138
- MFGraph = MaxFlow
139
145
  end
@@ -12,7 +12,7 @@ module AcLibraryRb
12
12
  @g_cost = Array.new(n) { [] }
13
13
  @pv = Array.new(n)
14
14
  @pe = Array.new(n)
15
- @dual = Array.new(n) { 0 }
15
+ @dual = Array.new(n, 0)
16
16
  end
17
17
 
18
18
  def add_edge(from, to, cap, cost)
@@ -37,6 +37,15 @@ module AcLibraryRb
37
37
  edge_number
38
38
  end
39
39
 
40
+ def add_edges(edges)
41
+ edges.each{ |from, to, cap, cost| add_edge(from, to, cap, cost) }
42
+ self
43
+ end
44
+
45
+ def add(x, to = nil, cap = nil, cost = nil)
46
+ cost ? add_edge(x, to, cap, cost) : add_edges(x)
47
+ end
48
+
40
49
  def get_edge(i)
41
50
  from, id = @pos[i]
42
51
  to = @g_to[from][id]
@@ -139,7 +148,4 @@ module AcLibraryRb
139
148
  end
140
149
  alias min_cost_slop slope
141
150
  end
142
-
143
- MCF = MinCostFlow
144
- MCFGraph = MinCostFlow
145
151
  end
@@ -2,18 +2,31 @@ module AcLibraryRb
2
2
  # Strongly Connected Components
3
3
  class SCC
4
4
  # initialize graph with n vertices
5
- def initialize(n = 0)
6
- @n, @edges = n, []
5
+ def initialize(n)
6
+ @n = n
7
+ @edges = []
7
8
  end
8
9
 
9
10
  # add directed edge
10
11
  def add_edge(from, to)
11
- raise "invalid params" unless (0...@n).include? from and (0...@n).include? to
12
+ unless 0 <= from && from < @n and 0 <= to && to < @n
13
+ msg = "Wrong params: from=#{from} and to=#{to} must be in 0...#{@n}"
14
+ raise ArgumentError.new(msg)
15
+ end
12
16
 
13
17
  @edges << [from, to]
14
18
  self
15
19
  end
16
20
 
21
+ def add_edges(edges)
22
+ edges.each{ |from, to| add_edge(from, to) }
23
+ self
24
+ end
25
+
26
+ def add(x, to = nil)
27
+ to ? add_edge(x, to) : add_edges(x)
28
+ end
29
+
17
30
  # returns list of strongly connected components
18
31
  # the components are sorted in topological order
19
32
  # O(@n + @edges.size)
@@ -59,7 +72,8 @@ module AcLibraryRb
59
72
  end
60
73
 
61
74
  def csr
62
- start, elist = [0] * (@n + 1), [nil] * @edges.size
75
+ start = [0] * (@n + 1)
76
+ elist = [nil] * @edges.size
63
77
  @edges.each { |(i, _)| start[i + 1] += 1 }
64
78
  @n.times { |i| start[i + 1] += start[i] }
65
79
  counter = start.dup
@@ -70,9 +84,4 @@ module AcLibraryRb
70
84
  [start, elist]
71
85
  end
72
86
  end
73
-
74
- # class alias
75
- StronglyConnectedComponents = SCC
76
- SCCGraph = SCC
77
- SCCG = SCC
78
87
  end
@@ -3,14 +3,10 @@ module AcLibraryRb
3
3
  class Segtree
4
4
  attr_reader :d, :op, :n, :leaf_size, :log
5
5
 
6
- # new(e){ |x, y| }
7
6
  # new(v, e){ |x, y| }
8
7
  # 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?
8
+ def initialize(a0, a1, a2 = nil, &block)
9
+ if a2.nil?
14
10
  @e, @op = a1, proc(&block)
15
11
  v = (a0.is_a?(Array) ? a0 : [@e] * a0)
16
12
  else
@@ -38,7 +34,18 @@ module AcLibraryRb
38
34
  end
39
35
  alias [] get
40
36
 
41
- def prod(l, r)
37
+ def prod(l, r = nil)
38
+ if r.nil? # if 1st argument l is Range
39
+ if r = l.end
40
+ r += @n if r < 0
41
+ r += 1 unless l.exclude_end?
42
+ else
43
+ r = @n
44
+ end
45
+ l = l.begin
46
+ l += @n if l < 0
47
+ end
48
+
42
49
  return @e if l == r
43
50
 
44
51
  sml = @e
@@ -130,7 +137,7 @@ module AcLibraryRb
130
137
 
131
138
  # def inspect # for debug
132
139
  # t = 0
133
- # res = "SegmentTree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
140
+ # res = "Segtree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
134
141
  # a = @d[1, @d.size - 1]
135
142
  # a.each_with_index do |e, i|
136
143
  # res << e.to_s << ' '
@@ -143,6 +150,5 @@ module AcLibraryRb
143
150
  # end
144
151
  end
145
152
 
146
- SegTree = Segtree
147
- SegmentTree = Segtree
153
+ SegTree = Segtree
148
154
  end
@@ -4,16 +4,18 @@ module AcLibraryRb
4
4
  # TwoSAT
5
5
  # Reference: https://github.com/atcoder/ac-library/blob/master/atcoder/twosat.hpp
6
6
  class TwoSAT
7
- def initialize(n = 0)
7
+ def initialize(n)
8
8
  @n = n
9
9
  @answer = Array.new(n)
10
- @scc = SCCGraph.new(2 * n)
10
+ @scc = SCC.new(2 * n)
11
11
  end
12
12
 
13
13
  attr_reader :answer
14
14
 
15
15
  def add_clause(i, f, j, g)
16
- raise RangeError unless (0...@n).cover?(i) && (0...@n).cover?(j)
16
+ unless 0 <= i && i < @n and 0 <= j && j < @n
17
+ raise RangeError.new
18
+ end
17
19
 
18
20
  @scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0))
19
21
  @scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0))
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.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - universato
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-06 00:00:00.000000000 Z
11
+ date: 2021-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: |-
42
56
  ac-library-rb is a ruby port of AtCoder Library (ACL).
43
57
  DSU(UnionFind), FenwickTree, PriorityQueue, Segtree, SCC, 2-SAT, suffix_array, lcp_array, z_algorithm, crt, inv_mod, floor_sum, max_flow, min_cost_flow......
@@ -90,6 +104,7 @@ files:
90
104
  - document_ja/two_sat.md
91
105
  - lib/ac-library-rb/version.rb
92
106
  - lib/convolution.rb
107
+ - lib/core_ext/all.rb
93
108
  - lib/core_ext/modint.rb
94
109
  - lib/crt.rb
95
110
  - lib/dsu.rb
@@ -111,6 +126,7 @@ files:
111
126
  - lib_helpers/ac-library-rb/all.rb
112
127
  - lib_lock/ac-library-rb.rb
113
128
  - lib_lock/ac-library-rb/convolution.rb
129
+ - lib_lock/ac-library-rb/core_ext/all.rb
114
130
  - lib_lock/ac-library-rb/core_ext/modint.rb
115
131
  - lib_lock/ac-library-rb/crt.rb
116
132
  - lib_lock/ac-library-rb/dsu.rb
@@ -151,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
167
  - !ruby/object:Gem::Version
152
168
  version: '0'
153
169
  requirements: []
154
- rubygems_version: 3.2.11
170
+ rubygems_version: 3.2.15
155
171
  signing_key:
156
172
  specification_version: 4
157
173
  summary: ac-library-rb is a ruby port of AtCoder Library (ACL).