Skip to content

Commit 4143784

Browse files
committed
Basic ARQ Tree documentation and toposort unit test
1 parent ae2ab8f commit 4143784

File tree

8 files changed

+129
-97
lines changed

8 files changed

+129
-97
lines changed

src/arq_tree.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Associative Range Query Tree based on http://codeforces.com/blog/entry/18051
2+
// Colloquially known as a "segtree" in the sport programming literature, it
3+
// represents a sequence of elements a_i (0 <= i < size) from a monoid (M, +) on
4+
// which we want to support fast range operations:
5+
// - modify(l, r, f) replaces a_i (l <= i <= r) by f(a_i) for a homomorphism f
6+
// - query(l, r) returns the aggregate a_l + a_{l+1} + ... + a_r
7+
//
8+
// To customize, simply change the commented lines.
9+
// In this example, we chose to support range sum queries and range constant
10+
// assignments. Since constant assignment f_c(a) = c is not a homomorphism over
11+
// integers, we have to augment the monoid type, using the 2D vector (a_i, 1)
12+
// instead of a_i. You may check that f_c((a, s)) = (c*s, s) is a homomorphism.
13+
pub struct ArqTree {
14+
d: Vec<Option<i64>>,
15+
t: Vec<i64>,
16+
s: Vec<i64>
17+
}
18+
19+
impl ArqTree {
20+
pub fn new(size: usize) -> ArqTree {
21+
let mut s = vec![1; 2*size];
22+
for i in (0..size).rev() {
23+
s[i] = s[i<<1] + s[i<<1|1];
24+
}
25+
ArqTree {
26+
d: vec![None; size],
27+
t: vec![0; 2*size], // monoid identity
28+
s: s
29+
}
30+
}
31+
32+
fn apply(&mut self, p: usize, f: i64) {
33+
self.t[p] = f * self.s[p]; // hom application
34+
if p < self.d.len() { self.d[p] = Some(f); } // hom composition
35+
}
36+
37+
fn push(&mut self, p: usize) {
38+
for s in (1..32).rev() {
39+
let i = p >> s;
40+
if let Some(f) = self.d[i] {
41+
self.apply(i<<1, f);
42+
self.apply(i<<1|1, f);
43+
self.d[i] = None;
44+
}
45+
}
46+
}
47+
48+
fn pull(&mut self, mut p: usize) {
49+
while p > 1 {
50+
p >>= 1;
51+
if self.d[p] == None {
52+
self.t[p] = self.t[p<<1] + self.t[p<<1|1]; // monoid op
53+
}
54+
}
55+
}
56+
57+
// Performs the homomorphism f on all entries from l to r, inclusive.
58+
pub fn modify(&mut self, mut l: usize, mut r: usize, f: i64) {
59+
l += self.d.len(); r += self.d.len();
60+
let (l0, r0) = (l, r);
61+
self.push(l0); self.push(r0);
62+
while l <= r {
63+
if l & 1 == 1 { self.apply(l, f); l += 1; }
64+
if r & 1 == 0 { self.apply(r, f); r -= 1; }
65+
l >>= 1; r >>= 1;
66+
}
67+
self.pull(l0); self.pull(r0);
68+
}
69+
70+
// Returns the aggregate range query on all entries from l to r, inclusive.
71+
pub fn query(&mut self, mut l: usize, mut r: usize) -> i64 {
72+
l += self.d.len(); r += self.d.len();
73+
self.push(l); self.push(r);
74+
let mut res = 0; // monoid identity
75+
while l <= r {
76+
if l & 1 == 1 { res = res + self.t[l]; l += 1; } // monoid op
77+
if r & 1 == 0 { res = self.t[r] + res; r -= 1; } // monoid op
78+
l >>= 1; r >>= 1;
79+
}
80+
res
81+
}
82+
}
83+
84+
#[cfg(test)]
85+
mod test {
86+
use super::*;
87+
88+
#[test]
89+
fn test_arq_tree()
90+
{
91+
let mut tree = ArqTree::new(10);
92+
93+
tree.modify(1, 3, 10);
94+
tree.modify(3, 5, 1);
95+
96+
assert_eq!(tree.query(0, 9), 23);
97+
}
98+
}
99+

src/arqtree.rs

Lines changed: 0 additions & 90 deletions
This file was deleted.

src/graph/connectivity.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ impl<'a> ConnectivityGraph<'a> {
8282
vertices
8383
}
8484

85-
// Biconnected components are a work in progress.
8685
fn bcc(&mut self, u: usize, par: usize, t: &mut usize, vis: &mut [usize],
8786
low: &mut [usize], verts: &mut Vec<usize>, edges: &mut Vec<usize>) {
8887
*t += 1;
@@ -144,6 +143,19 @@ impl<'a> ConnectivityGraph<'a> {
144143
mod test {
145144
use super::*;
146145

146+
#[test]
147+
fn test_toposort()
148+
{
149+
let mut graph = Graph::new(4, 4);
150+
graph.add_edge(0, 2);
151+
graph.add_edge(3, 2);
152+
graph.add_edge(3, 1);
153+
graph.add_edge(1, 0);
154+
155+
assert_eq!(ConnectivityGraph::new(&graph, true).topological_sort(),
156+
vec![3, 1, 0, 2]);
157+
}
158+
147159
#[test]
148160
fn test_two_sat()
149161
{
@@ -168,9 +180,12 @@ mod test {
168180
graph.add_undirected_edge(1, 2);
169181
graph.add_undirected_edge(1, 2);
170182

171-
let cc_graph = ConnectivityGraph::new(&graph, false);
172-
let bridges = (0..graph.num_e()).filter(|&e| cc_graph.is_cut_edge(e)).collect::<Vec<_>>();
173-
let articulation_points = (0..graph.num_v()).filter(|&u| cc_graph.is_cut_vertex(u)).collect::<Vec<_>>();
183+
let cg = ConnectivityGraph::new(&graph, false);
184+
let bridges = (0..graph.num_e())
185+
.filter(|&e| cg.is_cut_edge(e)).collect::<Vec<_>>();
186+
let articulation_points = (0..graph.num_v())
187+
.filter(|&u| cg.is_cut_vertex(u)).collect::<Vec<_>>();
188+
174189
assert_eq!(bridges, vec![0, 1]);
175190
assert_eq!(articulation_points, vec![1]);
176191
}

src/graph/flow.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ mod test {
165165
let mut graph = FlowGraph::new(3, 2);
166166
graph.add_edge(0, 1, 4, 1);
167167
graph.add_edge(1, 2, 3, 1);
168+
168169
let flow = graph.dinic(0, 2);
169170
assert_eq!(flow, 3);
170171
}
@@ -177,6 +178,7 @@ mod test {
177178
graph.add_edge(1, 2, 7, 8);
178179
graph.add_edge(2, 3, 7, 8);
179180
graph.add_edge(1, 3, 7, 10);
181+
180182
let (cost, flow) = graph.mcf(0, 3);
181183
assert_eq!(cost, 18);
182184
assert_eq!(flow, 10);

src/graph/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ mod test {
147147
graph.add_edge(1, 0);
148148
graph.add_edge(1, 2);
149149
graph.add_edge(2, 1);
150+
150151
assert_eq!(graph.euler_path(0), vec![0, 2, 3, 1]);
151152
}
152153

@@ -158,6 +159,7 @@ mod test {
158159
graph.add_undirected_edge(1, 2);
159160
graph.add_undirected_edge(2, 0);
160161
let weights = [7, 3, 5];
162+
161163
let mst = graph.min_spanning_tree(&weights);
162164
let mst_cost = mst.iter().map(|&e| weights[e]).sum::<i64>();
163165
assert_eq!(mst, vec![1, 2]);

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub mod arqtree;
1+
pub mod arq_tree;
22
pub mod graph;
33
pub mod math;
44
pub mod scanner;

src/math.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ mod test {
2828
use super::*;
2929

3030
#[test]
31-
fn test_gcd() {
31+
fn test_egcd() {
3232
let (a, b) = (14, 35);
33+
3334
let (d, x, y) = extended_gcd(a, b);
3435
assert_eq!(d, 7);
3536
assert_eq!(a*x + b*y, d);
37+
3638
assert_eq!(canon_egcd(a, b, d), Some((d, -2, 1)));
3739
assert_eq!(canon_egcd(b, a, d), Some((d, -1, 3)));
3840
}

src/string_proc.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ mod test {
6767
fn test_string() {
6868
let text = "abcbc".as_bytes();
6969
let pattern = "bc".as_bytes();
70+
7071
let matches = Matcher::new(pattern).kmp_match(text);
71-
let pal_len = palindromes(text);
7272
assert_eq!(matches, vec![0, 1, 2, 1, 2]);
73+
74+
let pal_len = palindromes(text);
7375
assert_eq!(pal_len, vec![1, 0, 1, 0, 3, 0, 3, 0, 1]);
7476
}
7577
}

0 commit comments

Comments
 (0)