ac-library-rb 0.5.2 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/README.md +9 -2
  4. data/ac-library-rb.gemspec +1 -0
  5. data/bin/lock_lib.rb +5 -1
  6. data/document_en/dsu.md +2 -2
  7. data/document_en/max_flow.md +1 -1
  8. data/document_en/min_cost_flow.md +1 -1
  9. data/document_en/segtree.md +22 -5
  10. data/document_en/two_sat.md +1 -1
  11. data/document_ja/dsu.md +1 -3
  12. data/document_ja/lazy_segtree.md +9 -7
  13. data/document_ja/max_flow.md +1 -1
  14. data/document_ja/min_cost_flow.md +1 -1
  15. data/document_ja/scc.md +4 -3
  16. data/document_ja/segtree.md +42 -9
  17. data/document_ja/two_sat.md +1 -1
  18. data/lib/ac-library-rb/version.rb +1 -1
  19. data/lib/convolution.rb +21 -0
  20. data/lib/core_ext/all.rb +11 -0
  21. data/lib/crt.rb +3 -1
  22. data/lib/dsu.rb +11 -8
  23. data/lib/fenwick_tree.rb +22 -8
  24. data/lib/floor_sum.rb +33 -10
  25. data/lib/lazy_segtree.rb +29 -3
  26. data/lib/max_flow.rb +10 -4
  27. data/lib/min_cost_flow.rb +13 -7
  28. data/lib/scc.rb +21 -13
  29. data/lib/segtree.rb +28 -22
  30. data/lib/two_sat.rb +7 -5
  31. data/lib_helpers/ac-library-rb.rb +24 -0
  32. data/lib_lock/ac-library-rb/convolution.rb +21 -0
  33. data/lib_lock/ac-library-rb/core_ext/all.rb +11 -0
  34. data/lib_lock/ac-library-rb/core_ext/modint.rb +3 -3
  35. data/lib_lock/ac-library-rb/crt.rb +3 -1
  36. data/lib_lock/ac-library-rb/dsu.rb +11 -8
  37. data/lib_lock/ac-library-rb/fenwick_tree.rb +22 -8
  38. data/lib_lock/ac-library-rb/floor_sum.rb +33 -10
  39. data/lib_lock/ac-library-rb/lazy_segtree.rb +29 -3
  40. data/lib_lock/ac-library-rb/max_flow.rb +10 -4
  41. data/lib_lock/ac-library-rb/min_cost_flow.rb +13 -7
  42. data/lib_lock/ac-library-rb/scc.rb +21 -13
  43. data/lib_lock/ac-library-rb/segtree.rb +28 -22
  44. data/lib_lock/ac-library-rb/two_sat.rb +7 -5
  45. metadata +20 -4
  46. data/lib_lock/ac-library-rb.rb +0 -22
@@ -0,0 +1,24 @@
1
+ module AcLibraryRb
2
+ end
3
+ include AcLibraryRb
4
+
5
+ require_relative '../lib_lock/ac-library-rb/core_ext/all.rb'
6
+
7
+ require_relative '../lib_lock/ac-library-rb/convolution'
8
+ require_relative '../lib_lock/ac-library-rb/crt'
9
+ require_relative '../lib_lock/ac-library-rb/dsu'
10
+ require_relative '../lib_lock/ac-library-rb/fenwick_tree'
11
+ require_relative '../lib_lock/ac-library-rb/floor_sum'
12
+ require_relative '../lib_lock/ac-library-rb/inv_mod'
13
+ require_relative '../lib_lock/ac-library-rb/lazy_segtree'
14
+ require_relative '../lib_lock/ac-library-rb/lcp_array'
15
+ require_relative '../lib_lock/ac-library-rb/max_flow'
16
+ require_relative '../lib_lock/ac-library-rb/min_cost_flow'
17
+ require_relative '../lib_lock/ac-library-rb/modint'
18
+ require_relative '../lib_lock/ac-library-rb/pow_mod'
19
+ require_relative '../lib_lock/ac-library-rb/priority_queue'
20
+ require_relative '../lib_lock/ac-library-rb/scc'
21
+ require_relative '../lib_lock/ac-library-rb/segtree'
22
+ require_relative '../lib_lock/ac-library-rb/suffix_array'
23
+ require_relative '../lib_lock/ac-library-rb/two_sat'
24
+ require_relative '../lib_lock/ac-library-rb/z_algorithm'
@@ -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,7 +1,9 @@
1
1
  module AcLibraryRb
2
2
  # return [rem, mod] or [0, 0] (if no solution)
3
3
  def crt(r, m)
4
- raise ArgumentError if r.size != m.size
4
+ unless r.size == m.size
5
+ raise ArgumentError.new("size of r and m must be equal for crt(r, m)")
6
+ end
5
7
 
6
8
  n = r.size
7
9
  r0, m0 = 0, 1
@@ -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)
@@ -20,12 +21,16 @@ module AcLibraryRb
20
21
  end
21
22
  alias unite merge
22
23
 
23
- def same(a, b)
24
+ def same?(a, b)
24
25
  leader(a) == leader(b)
25
26
  end
26
- alias same? same
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)
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
@@ -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]
@@ -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
@@ -1,16 +1,30 @@
1
1
  module AcLibraryRb
2
2
  # Strongly Connected Components
3
- class SCCGraph
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]
18
+ self
19
+ end
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)
14
28
  end
15
29
 
16
30
  # returns list of strongly connected components
@@ -18,10 +32,8 @@ module AcLibraryRb
18
32
  # O(@n + @edges.size)
19
33
  def scc
20
34
  group_num, ids = scc_ids
21
- counts = [0] * group_num
22
- ids.each { |x| counts[x] += 1 }
23
35
  groups = Array.new(group_num) { [] }
24
- ids.each_with_index { |x, i| groups[x] << i }
36
+ ids.each_with_index { |id, i| groups[id] << i }
25
37
  groups
26
38
  end
27
39
 
@@ -60,7 +72,8 @@ module AcLibraryRb
60
72
  end
61
73
 
62
74
  def csr
63
- start, elist = [0] * (@n + 1), [nil] * @edges.size
75
+ start = [0] * (@n + 1)
76
+ elist = [nil] * @edges.size
64
77
  @edges.each { |(i, _)| start[i + 1] += 1 }
65
78
  @n.times { |i| start[i + 1] += start[i] }
66
79
  counter = start.dup
@@ -71,9 +84,4 @@ module AcLibraryRb
71
84
  [start, elist]
72
85
  end
73
86
  end
74
-
75
- # class alias
76
- StronglyConnectedComponents = SCCGraph
77
- SCC = SCCGraph
78
- SCCG = SCCGraph
79
87
  end