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
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,11 +1,11 @@
1
1
  def ModInt(val)
2
- ModInt.new(val)
2
+ AcLibraryRb::ModInt.new(val)
3
3
  end
4
4
 
5
5
  # Integer
6
6
  class Integer
7
7
  def to_modint
8
- ModInt.new(self)
8
+ AcLibraryRb::ModInt.new(self)
9
9
  end
10
10
  alias to_m to_modint
11
11
  end
@@ -13,7 +13,7 @@ end
13
13
  # String
14
14
  class String
15
15
  def to_modint
16
- ModInt.new(to_i)
16
+ AcLibraryRb::ModInt.new(to_i)
17
17
  end
18
18
  alias to_m to_modint
19
19
  end
@@ -1,13 +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
+ @n = n
6
+ @parent_or_size = Array.new(n, -1)
5
7
  # root node: -1 * component size
6
8
  # otherwise: parent
7
- @parent_or_size = Array.new(n, -1)
8
9
  end
9
10
 
10
- attr_accessor :parent_or_size
11
+ attr_reader :parent_or_size, :n
11
12
 
12
13
  def merge(a, b)
13
14
  x = leader(a)
@@ -26,6 +27,10 @@ module AcLibraryRb
26
27
  alias same? same
27
28
 
28
29
  def leader(a)
30
+ unless 0 <= a && a < @n
31
+ raise ArgumentError.new, "#{a} is out of range (0...#{@n})"
32
+ end
33
+
29
34
  @parent_or_size[a] < 0 ? a : (@parent_or_size[a] = leader(@parent_or_size[a]))
30
35
  end
31
36
  alias root leader
@@ -40,7 +45,5 @@ module AcLibraryRb
40
45
  end
41
46
  end
42
47
 
43
- UnionFind = DSU
44
- UnionFindTree = DSU
45
- DisjointSetUnion = DSU
48
+ UnionFind = DSU
46
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)
@@ -42,9 +59,6 @@ module AcLibraryRb
42
59
  end
43
60
  res
44
61
  end
62
+ alias left_sum _sum
45
63
  end
46
-
47
- FeTree = FenwickTree
48
- Fetree = FenwickTree
49
- BinaryIndexedTree = FenwickTree
50
64
  end
@@ -1,23 +1,46 @@
1
1
  module AcLibraryRb
2
2
  def floor_sum(n, m, a, b)
3
+ raise ArgumentError if n < 0 || m < 1
4
+
3
5
  res = 0
4
6
 
5
- if a >= m
6
- res += (n - 1) * n * (a / m) / 2
7
- a %= m
7
+ if a < 0
8
+ a2 = a % m
9
+ res -= n * (n - 1) / 2 * ((a2 - a) / m)
10
+ a = a2
8
11
  end
9
12
 
10
- if b >= m
11
- res += n * (b / m)
12
- b %= m
13
+ if b < 0
14
+ b2 = b % m
15
+ res -= n * ((b2 - b) / m)
16
+ b = b2
13
17
  end
14
18
 
15
- y_max = (a * n + b) / m
19
+ res + floor_sum_unsigned(n, m, a, b)
20
+ end
21
+
22
+ def floor_sum_unsigned(n, m, a, b)
23
+ res = 0
24
+
25
+ while true
26
+ if a >= m
27
+ res += n * (n - 1) / 2 * (a / m)
28
+ a %= m
29
+ end
30
+
31
+ if b >= m
32
+ res += n * (b / m)
33
+ b %= m
34
+ end
16
35
 
17
- return res if y_max == 0
36
+ y_max = a * n + b
37
+ break if y_max < m
38
+
39
+ n = y_max / m
40
+ b = y_max % m
41
+ m, a = a, m
42
+ end
18
43
 
19
- x_max = (m * y_max - b + a - 1) / a
20
- res += (n - x_max) * y_max + floor_sum(y_max, a, m, a * x_max - m * y_max + b)
21
44
  res
22
45
  end
23
46
  end
@@ -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,20 +27,41 @@ 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
52
+
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
38
64
 
39
- def prod(l, r)
40
65
  return @e if l == r
41
66
 
42
67
  l += @size
@@ -69,7 +94,24 @@ module AcLibraryRb
69
94
  @d[1]
70
95
  end
71
96
 
72
- def apply(pos, f)
97
+ # apply(pos, f)
98
+ # apply(l, r, f) -> range_apply(l, r, f)
99
+ # apply(l...r, f) -> range_apply(l, r, f) ... [Experimental]
100
+ def apply(pos, f, fr = nil)
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
114
+
73
115
  pos += @size
74
116
  @log.downto(1) { |i| push(pos >> i) }
75
117
  @d[pos] = @mapping.call(f, @d[pos])
@@ -133,6 +175,35 @@ module AcLibraryRb
133
175
  @n
134
176
  end
135
177
 
178
+ def min_left(r, &g)
179
+ return 0 if r == 0
180
+
181
+ r += @size
182
+ @log.downto(1) { |i| push((r - 1) >> i) }
183
+ sm = @e
184
+
185
+ loop do
186
+ r -= 1
187
+ while r > 1 && r.odd?
188
+ r /= 2
189
+ end
190
+ unless g.call(@op.call(@d[r], sm))
191
+ while r < @size
192
+ push(r)
193
+ r = r * 2 + 1
194
+ if g.call(@op.call(@d[r], sm))
195
+ sm = @op.call(@d[r], sm)
196
+ r -= 1
197
+ end
198
+ end
199
+ return r + 1 - @size
200
+ end
201
+ sm = @op.call(@d[r], sm)
202
+ break if (r & -r) == r
203
+ end
204
+ 0
205
+ end
206
+
136
207
  def update(k)
137
208
  @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
138
209
  end
@@ -148,4 +219,6 @@ module AcLibraryRb
148
219
  @lz[k] = @id
149
220
  end
150
221
  end
222
+
223
+ LazySegTree = LazySegtree
151
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]
@@ -105,7 +114,7 @@ module AcLibraryRb
105
114
  def slope(s, t, flow_limit = Float::MAX)
106
115
  flow = 0
107
116
  cost = 0
108
- prev_cost = -1
117
+ prev_cost_per_flow = -1
109
118
  result = [[flow, cost]]
110
119
 
111
120
  while flow < flow_limit
@@ -130,16 +139,13 @@ module AcLibraryRb
130
139
  d = -@dual[s]
131
140
  flow += c
132
141
  cost += c * d
133
- result.pop if prev_cost == d
142
+ result.pop if prev_cost_per_flow == d
134
143
  result << [flow, cost]
135
- prev_cost = d
144
+ prev_cost_per_flow = d
136
145
  end
137
146
 
138
147
  result
139
148
  end
140
149
  alias min_cost_slop slope
141
150
  end
142
-
143
- MCF = MinCostFlow
144
- MCFGraph = MinCostFlow
145
151
  end