ac-library-rb 0.5.2 → 0.6.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/README.md +9 -2
- data/ac-library-rb.gemspec +1 -0
- data/bin/lock_lib.rb +5 -1
- data/document_en/dsu.md +2 -2
- data/document_en/max_flow.md +1 -1
- data/document_en/min_cost_flow.md +1 -1
- data/document_en/segtree.md +22 -5
- data/document_en/two_sat.md +1 -1
- data/document_ja/dsu.md +1 -3
- data/document_ja/lazy_segtree.md +9 -7
- data/document_ja/max_flow.md +1 -1
- data/document_ja/min_cost_flow.md +1 -1
- data/document_ja/scc.md +4 -3
- data/document_ja/segtree.md +42 -9
- data/document_ja/two_sat.md +1 -1
- data/lib/ac-library-rb/version.rb +1 -1
- data/lib/convolution.rb +21 -0
- data/lib/core_ext/all.rb +11 -0
- data/lib/crt.rb +3 -1
- data/lib/dsu.rb +11 -8
- data/lib/fenwick_tree.rb +22 -8
- data/lib/floor_sum.rb +33 -10
- data/lib/lazy_segtree.rb +29 -3
- data/lib/max_flow.rb +10 -4
- data/lib/min_cost_flow.rb +13 -7
- data/lib/scc.rb +21 -13
- data/lib/segtree.rb +28 -22
- data/lib/two_sat.rb +7 -5
- data/lib_helpers/ac-library-rb.rb +24 -0
- data/lib_lock/ac-library-rb/convolution.rb +21 -0
- data/lib_lock/ac-library-rb/core_ext/all.rb +11 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +3 -3
- data/lib_lock/ac-library-rb/crt.rb +3 -1
- data/lib_lock/ac-library-rb/dsu.rb +11 -8
- data/lib_lock/ac-library-rb/fenwick_tree.rb +22 -8
- data/lib_lock/ac-library-rb/floor_sum.rb +33 -10
- data/lib_lock/ac-library-rb/lazy_segtree.rb +29 -3
- data/lib_lock/ac-library-rb/max_flow.rb +10 -4
- data/lib_lock/ac-library-rb/min_cost_flow.rb +13 -7
- data/lib_lock/ac-library-rb/scc.rb +21 -13
- data/lib_lock/ac-library-rb/segtree.rb +28 -22
- data/lib_lock/ac-library-rb/two_sat.rb +7 -5
- metadata +20 -4
- 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
|
@@ -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
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
34
|
-
|
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
|
6
|
-
|
7
|
-
a
|
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
|
11
|
-
|
12
|
-
b
|
13
|
+
if b < 0
|
14
|
+
b2 = b % m
|
15
|
+
res -= n * ((b2 - b) / m)
|
16
|
+
b = b2
|
13
17
|
end
|
14
18
|
|
15
|
-
|
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
|
-
|
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)
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
142
|
+
result.pop if prev_cost_per_flow == d
|
134
143
|
result << [flow, cost]
|
135
|
-
|
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
|
3
|
+
class SCC
|
4
4
|
# initialize graph with n vertices
|
5
|
-
def initialize(n
|
6
|
-
@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
|
-
|
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 { |
|
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
|
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
|