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.
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