ac-library-rb 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/unittest.yml +16 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +198 -0
- data/Gemfile +3 -0
- data/LICENSE +116 -0
- data/README.ja.md +56 -0
- data/README.md +41 -0
- data/Rakefile +11 -0
- data/ac-library-rb.gemspec +32 -0
- data/bin/console +8 -0
- data/bin/lock_lib.rb +27 -0
- data/bin/setup +8 -0
- data/document_en/binary_index_tree.md +3 -0
- data/document_en/convolution.md +67 -0
- data/document_en/dsu.md +132 -0
- data/document_en/fenwick_tree.md +99 -0
- data/document_en/index.md +79 -0
- data/document_en/lazy_segtree.md +141 -0
- data/document_en/math.md +104 -0
- data/document_en/max_flow.md +165 -0
- data/document_en/min_cost_flow.md +132 -0
- data/document_en/modint.md +263 -0
- data/document_en/priority_queue.md +119 -0
- data/document_en/segtree.md +134 -0
- data/document_en/string.md +106 -0
- data/document_en/two_sat.md +91 -0
- data/document_en/union_find.md +3 -0
- data/document_ja/convolution.md +64 -0
- data/document_ja/dsu.md +183 -0
- data/document_ja/fenwick_tree.md +83 -0
- data/document_ja/index.md +89 -0
- data/document_ja/lazy_segtree.md +135 -0
- data/document_ja/math.md +116 -0
- data/document_ja/max_flow.md +129 -0
- data/document_ja/min_cost_flow.md +105 -0
- data/document_ja/modint.md +349 -0
- data/document_ja/priority_queue.md +103 -0
- data/document_ja/scc.md +65 -0
- data/document_ja/segtree.md +145 -0
- data/document_ja/string.md +105 -0
- data/document_ja/two_sat.md +87 -0
- data/lib/ac-library-rb/version.rb +3 -0
- data/lib/convolution.rb +124 -0
- data/lib/core_ext/modint.rb +19 -0
- data/lib/crt.rb +52 -0
- data/lib/dsu.rb +44 -0
- data/lib/fenwick_tree.rb +48 -0
- data/lib/floor_sum.rb +21 -0
- data/lib/inv_mod.rb +26 -0
- data/lib/lazy_segtree.rb +149 -0
- data/lib/lcp_array.rb +23 -0
- data/lib/max_flow.rb +137 -0
- data/lib/min_cost_flow.rb +143 -0
- data/lib/modint.rb +170 -0
- data/lib/pow_mod.rb +13 -0
- data/lib/priority_queue.rb +89 -0
- data/lib/scc.rb +77 -0
- data/lib/segtree.rb +140 -0
- data/lib/suffix_array.rb +128 -0
- data/lib/two_sat.rb +34 -0
- data/lib/z_algorithm.rb +32 -0
- data/lib_helpers/ac-library-rb/all.rb +22 -0
- data/lib_lock/ac-library-rb.rb +22 -0
- data/lib_lock/ac-library-rb/convolution.rb +126 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
- data/lib_lock/ac-library-rb/crt.rb +54 -0
- data/lib_lock/ac-library-rb/dsu.rb +46 -0
- data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
- data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
- data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
- data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
- data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
- data/lib_lock/ac-library-rb/max_flow.rb +139 -0
- data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
- data/lib_lock/ac-library-rb/modint.rb +172 -0
- data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
- data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
- data/lib_lock/ac-library-rb/scc.rb +79 -0
- data/lib_lock/ac-library-rb/segtree.rb +142 -0
- data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
- data/lib_lock/ac-library-rb/two_sat.rb +36 -0
- data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
- metadata +158 -0
@@ -0,0 +1,172 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
require_relative './core_ext/modint.rb'
|
3
|
+
|
4
|
+
# ModInt
|
5
|
+
class ModInt < Numeric
|
6
|
+
class << self
|
7
|
+
def set_mod(mod)
|
8
|
+
raise ArgumentError unless mod.is_a? Integer and 1 <= mod
|
9
|
+
|
10
|
+
$_mod = mod
|
11
|
+
$_mod_is_prime = ModInt.prime?(mod)
|
12
|
+
end
|
13
|
+
|
14
|
+
def mod=(mod)
|
15
|
+
set_mod mod
|
16
|
+
end
|
17
|
+
|
18
|
+
def mod
|
19
|
+
$_mod
|
20
|
+
end
|
21
|
+
|
22
|
+
def raw(val)
|
23
|
+
x = allocate
|
24
|
+
x.val = val.to_i
|
25
|
+
x
|
26
|
+
end
|
27
|
+
|
28
|
+
def prime?(n)
|
29
|
+
return false if n <= 1
|
30
|
+
return true if n == 2 or n == 7 or n == 61
|
31
|
+
return false if (n & 1) == 0
|
32
|
+
|
33
|
+
d = n - 1
|
34
|
+
d >>= 1 while (d & 1) == 0
|
35
|
+
[2, 7, 61].each do |a|
|
36
|
+
t = d
|
37
|
+
y = a.pow(t, n)
|
38
|
+
while t != n - 1 and y != 1 and y != n - 1
|
39
|
+
y = y * y % n
|
40
|
+
t <<= 1
|
41
|
+
end
|
42
|
+
return false if y != n - 1 and (t & 1) == 0
|
43
|
+
end
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def inv_gcd(a, b)
|
48
|
+
a %= b
|
49
|
+
return [b, 0] if a == 0
|
50
|
+
|
51
|
+
s, t = b, a
|
52
|
+
m0, m1 = 0, 1
|
53
|
+
while t != 0
|
54
|
+
u = s / t
|
55
|
+
s -= t * u
|
56
|
+
m0 -= m1 * u
|
57
|
+
s, t = t, s
|
58
|
+
m0, m1 = m1, m0
|
59
|
+
end
|
60
|
+
m0 += b / s if m0 < 0
|
61
|
+
[s, m0]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
attr_accessor :val
|
66
|
+
|
67
|
+
alias to_i val
|
68
|
+
|
69
|
+
def initialize(val = 0)
|
70
|
+
@val = val.to_i % $_mod
|
71
|
+
end
|
72
|
+
|
73
|
+
def inc!
|
74
|
+
@val += 1
|
75
|
+
@val = 0 if @val == $_mod
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def dec!
|
80
|
+
@val = $_mod if @val == 0
|
81
|
+
@val -= 1
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def add!(other)
|
86
|
+
@val = (@val + other.to_i) % $_mod
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def sub!(other)
|
91
|
+
@val = (@val - other.to_i) % $_mod
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def mul!(other)
|
96
|
+
@val = @val * other.to_i % $_mod
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
def div!(other)
|
101
|
+
mul! inv_internal(other.to_i)
|
102
|
+
end
|
103
|
+
|
104
|
+
def +@
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def -@
|
109
|
+
ModInt.raw($_mod - @val)
|
110
|
+
end
|
111
|
+
|
112
|
+
def **(other)
|
113
|
+
$_mod == 1 ? 0 : ModInt.raw(@val.pow(other, $_mod))
|
114
|
+
end
|
115
|
+
alias pow **
|
116
|
+
|
117
|
+
def inv
|
118
|
+
ModInt.raw(inv_internal(@val) % $_mod)
|
119
|
+
end
|
120
|
+
|
121
|
+
def coerce(other)
|
122
|
+
[ModInt(other), self]
|
123
|
+
end
|
124
|
+
|
125
|
+
def +(other)
|
126
|
+
dup.add! other
|
127
|
+
end
|
128
|
+
|
129
|
+
def -(other)
|
130
|
+
dup.sub! other
|
131
|
+
end
|
132
|
+
|
133
|
+
def *(other)
|
134
|
+
dup.mul! other
|
135
|
+
end
|
136
|
+
|
137
|
+
def /(other)
|
138
|
+
dup.div! other
|
139
|
+
end
|
140
|
+
|
141
|
+
def ==(other)
|
142
|
+
@val == other.to_i
|
143
|
+
end
|
144
|
+
|
145
|
+
def dup
|
146
|
+
ModInt.raw(@val)
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_int
|
150
|
+
@val
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_s
|
154
|
+
@val.to_s
|
155
|
+
end
|
156
|
+
|
157
|
+
def inspect
|
158
|
+
"#{@val} mod #{$_mod}"
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def inv_internal(a)
|
164
|
+
if $_mod_is_prime
|
165
|
+
a != 0 ? a.pow($_mod - 2, $_mod) : raise(RangeError, 'no inverse')
|
166
|
+
else
|
167
|
+
g, x = ModInt.inv_gcd(a, $_mod)
|
168
|
+
g == 1 ? x : raise(RangeError, 'no inverse')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Priority Queue
|
3
|
+
# Reference: https://github.com/python/cpython/blob/master/Lib/heapq.py
|
4
|
+
class PriorityQueue
|
5
|
+
# By default, the priority queue returns the maximum element first.
|
6
|
+
# If a block is given, the priority between the elements is determined with it.
|
7
|
+
# For example, the following block is given, the priority queue returns the minimum element first.
|
8
|
+
# `PriorityQueue.new { |x, y| x < y }`
|
9
|
+
#
|
10
|
+
# A heap is an array for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for all k, counting elements from 0.
|
11
|
+
def initialize(array = [], &comp)
|
12
|
+
@heap = array
|
13
|
+
@comp = comp || proc { |x, y| x > y }
|
14
|
+
heapify
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :heap
|
18
|
+
|
19
|
+
# Push new element to the heap.
|
20
|
+
def push(item)
|
21
|
+
shift_down(0, @heap.push(item).size - 1)
|
22
|
+
end
|
23
|
+
|
24
|
+
alias << push
|
25
|
+
alias append push
|
26
|
+
|
27
|
+
# Pop the element with the highest priority.
|
28
|
+
def pop
|
29
|
+
latest = @heap.pop
|
30
|
+
return latest if empty?
|
31
|
+
|
32
|
+
ret_item = heap[0]
|
33
|
+
heap[0] = latest
|
34
|
+
shift_up(0)
|
35
|
+
ret_item
|
36
|
+
end
|
37
|
+
|
38
|
+
# Get the element with the highest priority.
|
39
|
+
def get
|
40
|
+
@heap[0]
|
41
|
+
end
|
42
|
+
|
43
|
+
alias top get
|
44
|
+
|
45
|
+
# Returns true if the heap is empty.
|
46
|
+
def empty?
|
47
|
+
@heap.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def heapify
|
53
|
+
(@heap.size / 2 - 1).downto(0) { |i| shift_up(i) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def shift_up(pos)
|
57
|
+
end_pos = @heap.size
|
58
|
+
start_pos = pos
|
59
|
+
new_item = @heap[pos]
|
60
|
+
left_child_pos = 2 * pos + 1
|
61
|
+
|
62
|
+
while left_child_pos < end_pos
|
63
|
+
right_child_pos = left_child_pos + 1
|
64
|
+
if right_child_pos < end_pos && @comp.call(@heap[right_child_pos], @heap[left_child_pos])
|
65
|
+
left_child_pos = right_child_pos
|
66
|
+
end
|
67
|
+
# Move the higher priority child up.
|
68
|
+
@heap[pos] = @heap[left_child_pos]
|
69
|
+
pos = left_child_pos
|
70
|
+
left_child_pos = 2 * pos + 1
|
71
|
+
end
|
72
|
+
@heap[pos] = new_item
|
73
|
+
shift_down(start_pos, pos)
|
74
|
+
end
|
75
|
+
|
76
|
+
def shift_down(star_pos, pos)
|
77
|
+
new_item = @heap[pos]
|
78
|
+
while pos > star_pos
|
79
|
+
parent_pos = (pos - 1) >> 1
|
80
|
+
parent = @heap[parent_pos]
|
81
|
+
break if @comp.call(parent, new_item)
|
82
|
+
|
83
|
+
@heap[pos] = parent
|
84
|
+
pos = parent_pos
|
85
|
+
end
|
86
|
+
@heap[pos] = new_item
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
HeapQueue = PriorityQueue
|
91
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Strongly Connected Components
|
3
|
+
class SCCGraph
|
4
|
+
# initialize graph with n vertices
|
5
|
+
def initialize(n = 0)
|
6
|
+
@n, @edges = n, []
|
7
|
+
end
|
8
|
+
|
9
|
+
# add directed edge
|
10
|
+
def add_edge(from, to)
|
11
|
+
raise "invalid params" unless (0...@n).include? from and (0...@n).include? to
|
12
|
+
|
13
|
+
@edges << [from, to]
|
14
|
+
end
|
15
|
+
|
16
|
+
# returns list of strongly connected components
|
17
|
+
# the components are sorted in topological order
|
18
|
+
# O(@n + @edges.size)
|
19
|
+
def scc
|
20
|
+
group_num, ids = scc_ids
|
21
|
+
counts = [0] * group_num
|
22
|
+
ids.each { |x| counts[x] += 1 }
|
23
|
+
groups = Array.new(group_num) { [] }
|
24
|
+
ids.each_with_index { |x, i| groups[x] << i }
|
25
|
+
groups
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def scc_ids
|
31
|
+
start, elist = csr
|
32
|
+
now_ord = group_num = 0
|
33
|
+
visited, low, ord, ids = [], [], [-1] * @n, []
|
34
|
+
dfs = ->(v) {
|
35
|
+
low[v] = ord[v] = now_ord
|
36
|
+
now_ord += 1
|
37
|
+
visited << v
|
38
|
+
(start[v]...start[v + 1]).each do |i|
|
39
|
+
to = elist[i]
|
40
|
+
low[v] = if ord[to] == -1
|
41
|
+
dfs.(to)
|
42
|
+
[low[v], low[to]].min
|
43
|
+
else
|
44
|
+
[low[v], ord[to]].min
|
45
|
+
end
|
46
|
+
end
|
47
|
+
if low[v] == ord[v]
|
48
|
+
loop do
|
49
|
+
u = visited.pop
|
50
|
+
ord[u] = @n
|
51
|
+
ids[u] = group_num
|
52
|
+
break if u == v
|
53
|
+
end
|
54
|
+
group_num += 1
|
55
|
+
end
|
56
|
+
}
|
57
|
+
@n.times { |i| dfs.(i) if ord[i] == -1 }
|
58
|
+
ids = ids.map { |x| group_num - 1 - x }
|
59
|
+
[group_num, ids]
|
60
|
+
end
|
61
|
+
|
62
|
+
def csr
|
63
|
+
start, elist = [0] * (@n + 1), [nil] * @edges.size
|
64
|
+
@edges.each { |(i, _)| start[i + 1] += 1 }
|
65
|
+
@n.times { |i| start[i + 1] += start[i] }
|
66
|
+
counter = start.dup
|
67
|
+
@edges.each do |(i, j)|
|
68
|
+
elist[counter[i]] = j
|
69
|
+
counter[i] += 1
|
70
|
+
end
|
71
|
+
[start, elist]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# class alias
|
76
|
+
StronglyConnectedComponents = SCCGraph
|
77
|
+
SCC = SCCGraph
|
78
|
+
SCCG = SCCGraph
|
79
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# Segment Tree
|
3
|
+
class Segtree
|
4
|
+
attr_reader :d, :op, :n, :leaf_size, :log
|
5
|
+
|
6
|
+
def initialize(arg = 0, e, &block)
|
7
|
+
case arg
|
8
|
+
when Integer
|
9
|
+
v = Array.new(arg) { e }
|
10
|
+
when Array
|
11
|
+
v = arg
|
12
|
+
end
|
13
|
+
|
14
|
+
@e = e
|
15
|
+
@op = proc(&block)
|
16
|
+
|
17
|
+
@n = v.size
|
18
|
+
@log = (@n - 1).bit_length
|
19
|
+
@leaf_size = 1 << @log
|
20
|
+
@d = Array.new(@leaf_size * 2) { e }
|
21
|
+
v.each_with_index { |v_i, i| @d[@leaf_size + i] = v_i }
|
22
|
+
(@leaf_size - 1).downto(1) { |i| update(i) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(q, x)
|
26
|
+
q += @leaf_size
|
27
|
+
@d[q] = x
|
28
|
+
1.upto(@log) { |i| update(q >> i) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(pos)
|
32
|
+
@d[@leaf_size + pos]
|
33
|
+
end
|
34
|
+
|
35
|
+
def prod(l, r)
|
36
|
+
return @e if l == r
|
37
|
+
|
38
|
+
sml = @e
|
39
|
+
smr = @e
|
40
|
+
l += @leaf_size
|
41
|
+
r += @leaf_size
|
42
|
+
|
43
|
+
while l < r
|
44
|
+
if l[0] == 1
|
45
|
+
sml = @op.call(sml, @d[l])
|
46
|
+
l += 1
|
47
|
+
end
|
48
|
+
if r[0] == 1
|
49
|
+
r -= 1
|
50
|
+
smr = @op.call(@d[r], smr)
|
51
|
+
end
|
52
|
+
l /= 2
|
53
|
+
r /= 2
|
54
|
+
end
|
55
|
+
|
56
|
+
@op.call(sml, smr)
|
57
|
+
end
|
58
|
+
|
59
|
+
def all_prod
|
60
|
+
@d[1]
|
61
|
+
end
|
62
|
+
|
63
|
+
def max_right(l, &block)
|
64
|
+
return @n if l == @n
|
65
|
+
|
66
|
+
f = proc(&block)
|
67
|
+
|
68
|
+
l += @leaf_size
|
69
|
+
sm = @e
|
70
|
+
loop do
|
71
|
+
l /= 2 while l.even?
|
72
|
+
unless f.call(@op.call(sm, @d[l]))
|
73
|
+
while l < @leaf_size
|
74
|
+
l *= 2
|
75
|
+
if f.call(@op.call(sm, @d[l]))
|
76
|
+
sm = @op.call(sm, @d[l])
|
77
|
+
l += 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
return l - @leaf_size
|
82
|
+
end
|
83
|
+
|
84
|
+
sm = @op.call(sm, @d[l])
|
85
|
+
l += 1
|
86
|
+
break if (l & -l) == l
|
87
|
+
end
|
88
|
+
|
89
|
+
@n
|
90
|
+
end
|
91
|
+
|
92
|
+
def min_left(r, &block)
|
93
|
+
return 0 if r == 0
|
94
|
+
|
95
|
+
f = proc(&block)
|
96
|
+
|
97
|
+
r += @leaf_size
|
98
|
+
sm = @e
|
99
|
+
loop do
|
100
|
+
r -= 1
|
101
|
+
r /= 2 while r > 1 && r.odd?
|
102
|
+
unless f.call(@op.call(@d[r], sm))
|
103
|
+
while r < @leaf_size
|
104
|
+
r = r * 2 + 1
|
105
|
+
if f.call(@op.call(@d[r], sm))
|
106
|
+
sm = @op.call(@d[r], sm)
|
107
|
+
r -= 1
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
return r + 1 - @leaf_size
|
112
|
+
end
|
113
|
+
|
114
|
+
sm = @op.call(@d[r], sm)
|
115
|
+
break if (r & -r) == r
|
116
|
+
end
|
117
|
+
|
118
|
+
0
|
119
|
+
end
|
120
|
+
|
121
|
+
def update(k)
|
122
|
+
@d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
|
123
|
+
end
|
124
|
+
|
125
|
+
def inspect
|
126
|
+
t = 0
|
127
|
+
res = "SegmentTree @e = #{@e}, @n = #{@n}, @leaf_size = #{@leaf_size} @op = #{@op}\n "
|
128
|
+
a = @d[1, @d.size - 1]
|
129
|
+
a.each_with_index do |e, i|
|
130
|
+
res << e.to_s << ' '
|
131
|
+
if t == i && i < @leaf_size
|
132
|
+
res << "\n "
|
133
|
+
t = t * 2 + 2
|
134
|
+
end
|
135
|
+
end
|
136
|
+
res
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
SegTree = Segtree
|
141
|
+
SegmentTree = Segtree
|
142
|
+
end
|