ac-library-rb 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/unittest.yml +16 -0
  3. data/.gitignore +11 -0
  4. data/.rubocop.yml +198 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +116 -0
  7. data/README.ja.md +56 -0
  8. data/README.md +41 -0
  9. data/Rakefile +11 -0
  10. data/ac-library-rb.gemspec +32 -0
  11. data/bin/console +8 -0
  12. data/bin/lock_lib.rb +27 -0
  13. data/bin/setup +8 -0
  14. data/document_en/binary_index_tree.md +3 -0
  15. data/document_en/convolution.md +67 -0
  16. data/document_en/dsu.md +132 -0
  17. data/document_en/fenwick_tree.md +99 -0
  18. data/document_en/index.md +79 -0
  19. data/document_en/lazy_segtree.md +141 -0
  20. data/document_en/math.md +104 -0
  21. data/document_en/max_flow.md +165 -0
  22. data/document_en/min_cost_flow.md +132 -0
  23. data/document_en/modint.md +263 -0
  24. data/document_en/priority_queue.md +119 -0
  25. data/document_en/segtree.md +134 -0
  26. data/document_en/string.md +106 -0
  27. data/document_en/two_sat.md +91 -0
  28. data/document_en/union_find.md +3 -0
  29. data/document_ja/convolution.md +64 -0
  30. data/document_ja/dsu.md +183 -0
  31. data/document_ja/fenwick_tree.md +83 -0
  32. data/document_ja/index.md +89 -0
  33. data/document_ja/lazy_segtree.md +135 -0
  34. data/document_ja/math.md +116 -0
  35. data/document_ja/max_flow.md +129 -0
  36. data/document_ja/min_cost_flow.md +105 -0
  37. data/document_ja/modint.md +349 -0
  38. data/document_ja/priority_queue.md +103 -0
  39. data/document_ja/scc.md +65 -0
  40. data/document_ja/segtree.md +145 -0
  41. data/document_ja/string.md +105 -0
  42. data/document_ja/two_sat.md +87 -0
  43. data/lib/ac-library-rb/version.rb +3 -0
  44. data/lib/convolution.rb +124 -0
  45. data/lib/core_ext/modint.rb +19 -0
  46. data/lib/crt.rb +52 -0
  47. data/lib/dsu.rb +44 -0
  48. data/lib/fenwick_tree.rb +48 -0
  49. data/lib/floor_sum.rb +21 -0
  50. data/lib/inv_mod.rb +26 -0
  51. data/lib/lazy_segtree.rb +149 -0
  52. data/lib/lcp_array.rb +23 -0
  53. data/lib/max_flow.rb +137 -0
  54. data/lib/min_cost_flow.rb +143 -0
  55. data/lib/modint.rb +170 -0
  56. data/lib/pow_mod.rb +13 -0
  57. data/lib/priority_queue.rb +89 -0
  58. data/lib/scc.rb +77 -0
  59. data/lib/segtree.rb +140 -0
  60. data/lib/suffix_array.rb +128 -0
  61. data/lib/two_sat.rb +34 -0
  62. data/lib/z_algorithm.rb +32 -0
  63. data/lib_helpers/ac-library-rb/all.rb +22 -0
  64. data/lib_lock/ac-library-rb.rb +22 -0
  65. data/lib_lock/ac-library-rb/convolution.rb +126 -0
  66. data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
  67. data/lib_lock/ac-library-rb/crt.rb +54 -0
  68. data/lib_lock/ac-library-rb/dsu.rb +46 -0
  69. data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
  70. data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
  71. data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
  72. data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
  73. data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
  74. data/lib_lock/ac-library-rb/max_flow.rb +139 -0
  75. data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
  76. data/lib_lock/ac-library-rb/modint.rb +172 -0
  77. data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
  78. data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
  79. data/lib_lock/ac-library-rb/scc.rb +79 -0
  80. data/lib_lock/ac-library-rb/segtree.rb +142 -0
  81. data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
  82. data/lib_lock/ac-library-rb/two_sat.rb +36 -0
  83. data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
  84. metadata +158 -0
@@ -0,0 +1,151 @@
1
+ module AcLibraryRb
2
+ # Segment tree with Lazy propagation
3
+ class LazySegtree
4
+ attr_reader :d, :lz
5
+ attr_accessor :op, :mapping, :composition
6
+
7
+ def initialize(v, e, id, op, mapping, composition)
8
+ v = Array.new(v, e) if v.is_a?(Integer)
9
+
10
+ @n = v.size
11
+ @e = e
12
+ @id = id
13
+ @op = op
14
+ @mapping = mapping
15
+ @composition = composition
16
+
17
+ @log = (@n - 1).bit_length
18
+ @size = 1 << @log
19
+ @d = Array.new(2 * @size, e)
20
+ @lz = Array.new(@size, id)
21
+
22
+ @n.times { |i| @d[@size + i] = v[i] }
23
+ (@size - 1).downto(1) { |i| update(i) }
24
+ end
25
+
26
+ def set(pos, x)
27
+ pos += @size
28
+ @log.downto(1) { |i| push(pos >> i) }
29
+ @d[pos] = x
30
+ 1.upto(@log) { |i| update(pos >> i) }
31
+ end
32
+
33
+ def get(pos)
34
+ pos += @size
35
+ @log.downto(1) { |i| push(pos >> i) }
36
+ @d[pos]
37
+ end
38
+
39
+ def prod(l, r)
40
+ return @e if l == r
41
+
42
+ l += @size
43
+ r += @size
44
+
45
+ @log.downto(1) do |i|
46
+ push(l >> i) if (l >> i) << i != l
47
+ push(r >> i) if (r >> i) << i != r
48
+ end
49
+
50
+ sml = @e
51
+ smr = @e
52
+ while l < r
53
+ if l.odd?
54
+ sml = @op.call(sml, @d[l])
55
+ l += 1
56
+ end
57
+ if r.odd?
58
+ r -= 1
59
+ smr = @op.call(@d[r], smr)
60
+ end
61
+ l >>= 1
62
+ r >>= 1
63
+ end
64
+
65
+ @op.call(sml, smr)
66
+ end
67
+
68
+ def all_prod
69
+ @d[1]
70
+ end
71
+
72
+ def apply(pos, f)
73
+ pos += @size
74
+ @log.downto(1) { |i| push(pos >> i) }
75
+ @d[pos] = @mapping.call(f, @d[pos])
76
+ 1.upto(@log) { |i| update(pos >> i) }
77
+ end
78
+
79
+ def range_apply(l, r, f)
80
+ return if l == r
81
+
82
+ l += @size
83
+ r += @size
84
+
85
+ @log.downto(1) do |i|
86
+ push(l >> i) if (l >> i) << i != l
87
+ push((r - 1) >> i) if (r >> i) << i != r
88
+ end
89
+
90
+ l2 = l
91
+ r2 = r
92
+ while l < r
93
+ (all_apply(l, f); l += 1) if l.odd?
94
+ (r -= 1; all_apply(r, f)) if r.odd?
95
+ l >>= 1
96
+ r >>= 1
97
+ end
98
+ l = l2
99
+ r = r2
100
+
101
+ 1.upto(@log) do |i|
102
+ update(l >> i) if (l >> i) << i != l
103
+ update((r - 1) >> i) if (r >> i) << i != r
104
+ end
105
+ end
106
+
107
+ def max_right(l, &g)
108
+ return @n if l == @n
109
+
110
+ l += @size
111
+ @log.downto(1) { |i| push(l >> i) }
112
+ sm = @e
113
+
114
+ loop do
115
+ while l.even?
116
+ l >>= 1
117
+ end
118
+ unless g.call(@op.call(sm, @d[l]))
119
+ while l < @size
120
+ push(l)
121
+ l <<= 1
122
+ if g.call(@op.call(sm, @d[l]))
123
+ sm = @op.call(sm, @d[l])
124
+ l += 1
125
+ end
126
+ end
127
+ return l - @size
128
+ end
129
+ sm = @op.call(sm, @d[l])
130
+ l += 1
131
+ break if l & -l == l
132
+ end
133
+ @n
134
+ end
135
+
136
+ def update(k)
137
+ @d[k] = @op.call(@d[2 * k], @d[2 * k + 1])
138
+ end
139
+
140
+ def all_apply(k, f)
141
+ @d[k] = @mapping.call(f, @d[k])
142
+ @lz[k] = @composition.call(f, @lz[k]) if k < @size
143
+ end
144
+
145
+ def push(k)
146
+ all_apply(2 * k, @lz[k])
147
+ all_apply(2 * k + 1, @lz[k])
148
+ @lz[k] = @id
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,25 @@
1
+ module AcLibraryRb
2
+ # lcp array for array of integers or string
3
+ def lcp_array(s, sa)
4
+ s = s.bytes if s.is_a?(String)
5
+
6
+ n = s.size
7
+ rnk = [0] * n
8
+ sa.each_with_index{ |sa, id|
9
+ rnk[sa] = id
10
+ }
11
+
12
+ lcp = [0] * (n - 1)
13
+ h = 0
14
+ n.times{ |i|
15
+ h -= 1 if h > 0
16
+ next if rnk[i] == 0
17
+
18
+ j = sa[rnk[i] - 1]
19
+ h += 1 while j + h < n && i + h < n && s[j + h] == s[i + h]
20
+ lcp[rnk[i] - 1] = h
21
+ }
22
+
23
+ return lcp
24
+ end
25
+ end
@@ -0,0 +1,139 @@
1
+ module AcLibraryRb
2
+ # MaxFlowGraph
3
+ class MaxFlow
4
+ def initialize(n = 0)
5
+ @n = n
6
+ @pos = []
7
+ @g = Array.new(n) { [] }
8
+ end
9
+
10
+ def add_edge(from, to, cap)
11
+ edge_number = @pos.size
12
+
13
+ @pos << [from, @g[from].size]
14
+
15
+ from_id = @g[from].size
16
+ to_id = @g[to].size
17
+ to_id += 1 if from == to
18
+ @g[from] << [to, to_id, cap]
19
+ @g[to] << [from, from_id, 0]
20
+
21
+ edge_number
22
+ end
23
+
24
+ def push(edge)
25
+ add_edge(*edge)
26
+ end
27
+ alias << push
28
+
29
+ # return edge = [from, to, cap, flow]
30
+ def [](i)
31
+ _e = @g[@pos[i][0]][@pos[i][1]]
32
+ _re = @g[_e[0]][_e[1]]
33
+ [@pos[i][0], _e[0], _e[-1] + _re[-1], _re[-1]]
34
+ end
35
+ alias get_edge []
36
+ alias edge []
37
+
38
+ def edges
39
+ @pos.map do |(from, id)|
40
+ _e = @g[from][id]
41
+ _re = @g[_e[0]][_e[1]]
42
+ [from, _e[0], _e[-1] + _re[-1], _re[-1]]
43
+ end
44
+ end
45
+
46
+ def change_edge(i, new_cap, new_flow)
47
+ _e = @g[@pos[i][0]][@pos[i][1]]
48
+ _re = @g[_e[0]][_e[1]]
49
+ _e[2] = new_cap - new_flow
50
+ _re[2] = new_flow
51
+ end
52
+
53
+ def flow(s, t, flow_limit = 1 << 64)
54
+ level = Array.new(@n)
55
+ iter = Array.new(@n)
56
+ que = []
57
+
58
+ flow = 0
59
+ while flow < flow_limit
60
+ bfs(s, t, level, que)
61
+ break if level[t] == -1
62
+
63
+ iter.fill(0)
64
+ while flow < flow_limit
65
+ f = dfs(t, flow_limit - flow, s, level, iter)
66
+ break if f == 0
67
+
68
+ flow += f
69
+ end
70
+ end
71
+
72
+ flow
73
+ end
74
+ alias max_flow flow
75
+
76
+ def min_cut(s)
77
+ visited = Array.new(@n, false)
78
+ que = [s]
79
+ while (q = que.shift)
80
+ visited[q] = true
81
+ @g[q].each do |(to, _rev, cap)|
82
+ if cap > 0 && !visited[to]
83
+ visited[to] = true
84
+ que << to
85
+ end
86
+ end
87
+ end
88
+ visited
89
+ end
90
+
91
+ private
92
+
93
+ def bfs(s, t, level, que)
94
+ level.fill(-1)
95
+ level[s] = 0
96
+ que.clear
97
+ que << s
98
+
99
+ while (v = que.shift)
100
+ @g[v].each do |e|
101
+ next if e[2] == 0 || level[e[0]] >= 0
102
+
103
+ level[e[0]] = level[v] + 1
104
+ return nil if e[0] == t
105
+
106
+ que << e[0]
107
+ end
108
+ end
109
+ end
110
+
111
+ def dfs(v, up, s, level, iter)
112
+ return up if v == s
113
+
114
+ res = 0
115
+ level_v = level[v]
116
+
117
+ while iter[v] < @g[v].size
118
+ i = iter[v]
119
+ e = @g[v][i]
120
+ cap = @g[e[0]][e[1]][2]
121
+ if level_v > level[e[0]] && cap > 0
122
+ d = dfs(e[0], (up - res < cap ? up - res : cap), s, level, iter)
123
+ if d > 0
124
+ @g[v][i][2] += d
125
+ @g[e[0]][e[1]][2] -= d
126
+ res += d
127
+ break if res == up
128
+ end
129
+ end
130
+ iter[v] += 1
131
+ end
132
+
133
+ res
134
+ end
135
+ end
136
+
137
+ MaxFlowGraph = MaxFlow
138
+ MFGraph = MaxFlow
139
+ end
@@ -0,0 +1,145 @@
1
+ module AcLibraryRb
2
+ require_relative './priority_queue.rb'
3
+
4
+ # Min Cost Flow Grapsh
5
+ class MinCostFlow
6
+ def initialize(n)
7
+ @n = n
8
+ @pos = []
9
+ @g_to = Array.new(n) { [] }
10
+ @g_rev = Array.new(n) { [] }
11
+ @g_cap = Array.new(n) { [] }
12
+ @g_cost = Array.new(n) { [] }
13
+ @pv = Array.new(n)
14
+ @pe = Array.new(n)
15
+ @dual = Array.new(n) { 0 }
16
+ end
17
+
18
+ def add_edge(from, to, cap, cost)
19
+ edge_number = @pos.size
20
+
21
+ @pos << [from, @g_to[from].size]
22
+
23
+ from_id = @g_to[from].size
24
+ to_id = @g_to[to].size
25
+ to_id += 1 if from == to
26
+
27
+ @g_to[from] << to
28
+ @g_rev[from] << to_id
29
+ @g_cap[from] << cap
30
+ @g_cost[from] << cost
31
+
32
+ @g_to[to] << from
33
+ @g_rev[to] << from_id
34
+ @g_cap[to] << 0
35
+ @g_cost[to] << -cost
36
+
37
+ edge_number
38
+ end
39
+
40
+ def get_edge(i)
41
+ from, id = @pos[i]
42
+ to = @g_to[from][id]
43
+ rid = @g_rev[from][id]
44
+ [from, to, @g_cap[from][id] + @g_cap[to][rid], @g_cap[to][rid], @g_cost[from][id]]
45
+ end
46
+ alias edge get_edge
47
+ alias [] get_edge
48
+
49
+ def edges
50
+ @pos.map do |(from, id)|
51
+ to = @g_to[from][id]
52
+ rid = @g_rev[from][id]
53
+ [from, to, @g_cap[from][id] + @g_cap[to][rid], @g_cap[to][rid], @g_cost[from][id]]
54
+ end
55
+ end
56
+
57
+ def flow(s, t, flow_limit = Float::MAX)
58
+ slope(s, t, flow_limit).last
59
+ end
60
+ alias min_cost_max_flow flow
61
+
62
+ def dual_ref(s, t)
63
+ dist = Array.new(@n, Float::MAX)
64
+ @pv.fill(-1)
65
+ @pe.fill(-1)
66
+ vis = Array.new(@n, false)
67
+
68
+ que = PriorityQueue.new { |par, chi| par[0] < chi[0] }
69
+ dist[s] = 0
70
+ que.push([0, s])
71
+
72
+ while (v = que.pop)
73
+ v = v[1]
74
+
75
+ next if vis[v]
76
+
77
+ vis[v] = true
78
+ break if v == t
79
+
80
+ @g_to[v].size.times do |i|
81
+ to = @g_to[v][i]
82
+ next if vis[to] || @g_cap[v][i] == 0
83
+
84
+ cost = @g_cost[v][i] - @dual[to] + @dual[v]
85
+ next unless dist[to] - dist[v] > cost
86
+
87
+ dist[to] = dist[v] + cost
88
+ @pv[to] = v
89
+ @pe[to] = i
90
+ que.push([dist[to], to])
91
+ end
92
+ end
93
+
94
+ return false unless vis[t]
95
+
96
+ @n.times do |i|
97
+ next unless vis[i]
98
+
99
+ @dual[i] -= dist[t] - dist[i]
100
+ end
101
+
102
+ true
103
+ end
104
+
105
+ def slope(s, t, flow_limit = Float::MAX)
106
+ flow = 0
107
+ cost = 0
108
+ prev_cost = -1
109
+ result = [[flow, cost]]
110
+
111
+ while flow < flow_limit
112
+ break unless dual_ref(s, t)
113
+
114
+ c = flow_limit - flow
115
+ v = t
116
+ while v != s
117
+ c = @g_cap[@pv[v]][@pe[v]] if c > @g_cap[@pv[v]][@pe[v]]
118
+ v = @pv[v]
119
+ end
120
+
121
+ v = t
122
+ while v != s
123
+ nv = @pv[v]
124
+ id = @pe[v]
125
+ @g_cap[nv][id] -= c
126
+ @g_cap[v][@g_rev[nv][id]] += c
127
+ v = nv
128
+ end
129
+
130
+ d = -@dual[s]
131
+ flow += c
132
+ cost += c * d
133
+ result.pop if prev_cost == d
134
+ result << [flow, cost]
135
+ prev_cost = d
136
+ end
137
+
138
+ result
139
+ end
140
+ alias min_cost_slop slope
141
+ end
142
+
143
+ MCF = MinCostFlow
144
+ MCFGraph = MinCostFlow
145
+ end