ac-library-rb 0.5.4 → 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.
- checksums.yaml +4 -4
- data/ac-library-rb.gemspec +1 -0
- data/bin/lock_lib.rb +1 -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 +5 -2
- data/document_en/two_sat.md +1 -1
- data/document_ja/dsu.md +1 -3
- 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 +2 -1
- 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/dsu.rb +4 -6
- data/lib/fenwick_tree.rb +21 -8
- data/lib/lazy_segtree.rb +29 -3
- data/lib/max_flow.rb +10 -4
- data/lib/min_cost_flow.rb +10 -4
- data/lib/scc.rb +18 -9
- data/lib/segtree.rb +16 -10
- data/lib/two_sat.rb +5 -3
- data/lib_lock/ac-library-rb.rb +2 -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/dsu.rb +4 -6
- data/lib_lock/ac-library-rb/fenwick_tree.rb +21 -8
- 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 +10 -4
- data/lib_lock/ac-library-rb/scc.rb +18 -9
- data/lib_lock/ac-library-rb/segtree.rb +16 -10
- data/lib_lock/ac-library-rb/two_sat.rb +5 -3
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f191f90563fea038c7181e2bf9d13e1dc8caa0e816a364176e46b67c8d63f471
|
4
|
+
data.tar.gz: c89db082816046146cb60faa3747e046877394bfff776a3defe8063fb2d1c390
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0114099d09f9566741d84ed2b5e43427b62592bb8b2a6b90d25b9f68288d2a387f34899351d18a7b3e0c93ec72af9cae4aac2f1d38f5fe517e30ec850e33429e'
|
7
|
+
data.tar.gz: cdb1eac1808855f86c00c991b4c66ae3489035420ef0fdb8c88915712ace8faa5db02da074a78734e0c4235058ac1e2a62a0fc9cc0523e6c85aff4617b47ae39
|
data/ac-library-rb.gemspec
CHANGED
@@ -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
|
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`, `
|
44
|
+
- `DSU`, `UnionFind`
|
45
45
|
|
46
46
|
## Instance Methods
|
47
47
|
|
data/document_en/max_flow.md
CHANGED
data/document_en/segtree.md
CHANGED
@@ -4,7 +4,8 @@ Segment Tree
|
|
4
4
|
|
5
5
|
## Class Methods
|
6
6
|
|
7
|
-
### new(n, e,
|
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
|
-
|
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| ... }
|
data/document_en/two_sat.md
CHANGED
data/document_ja/dsu.md
CHANGED
@@ -30,7 +30,7 @@ p d.size(2) # => 2
|
|
30
30
|
|
31
31
|
## 特異メソッド
|
32
32
|
|
33
|
-
### new(n
|
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
|
|
data/document_ja/max_flow.md
CHANGED
data/document_ja/scc.md
CHANGED
@@ -6,7 +6,7 @@ Strongly Connected Components
|
|
6
6
|
|
7
7
|
## 特異メソッド
|
8
8
|
|
9
|
-
### new(n
|
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
|
|
data/document_ja/segtree.md
CHANGED
data/document_ja/two_sat.md
CHANGED
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
|
data/lib/core_ext/all.rb
ADDED
data/lib/dsu.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# Disjoint Set Union
|
2
2
|
class DSU
|
3
|
-
def initialize(n
|
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
|
-
|
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
|
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
|
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 =
|
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
|
-
|
33
|
-
|
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)
|
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
|
-
|
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
|
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
|
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
|
5
|
-
@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
|
-
|
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
|
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
|
9
|
-
if
|
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 = "
|
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
|
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
|
6
|
+
def initialize(n)
|
7
7
|
@n = n
|
8
8
|
@answer = Array.new(n)
|
9
|
-
@scc =
|
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
|
-
|
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))
|
data/lib_lock/ac-library-rb.rb
CHANGED
@@ -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,14 +1,14 @@
|
|
1
1
|
module AcLibraryRb
|
2
2
|
# Disjoint Set Union
|
3
3
|
class DSU
|
4
|
-
def initialize(n
|
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
|
-
|
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
|
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
|
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 =
|
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
|
-
|
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)
|
@@ -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)
|
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]
|
@@ -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
|
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]
|
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
|
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
|
10
|
-
if
|
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 = "
|
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
|
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
|
7
|
+
def initialize(n)
|
8
8
|
@n = n
|
9
9
|
@answer = Array.new(n)
|
10
|
-
@scc =
|
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
|
-
|
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.
|
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-
|
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.
|
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).
|