Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f5c3543

Browse files
committed
coordinate compression and ArqSpec documentation on point queries
1 parent fb0a9ed commit f5c3543

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

‎README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ Rather than try to persuade you with words, this repository aims to show by exam
4444
## Contents
4545

4646
- [Basic graph representations](src/graph/mod.rs): adjacency lists, disjoint set union
47-
- [Elementary Graph algorithms](src/graph/util.rs): minimum spanning tree, Euler path, Dijkstra's algorithm, DFS iteration
47+
- [Elementary graph algorithms](src/graph/util.rs): minimum spanning tree, Euler path, Dijkstra's algorithm, DFS iteration
4848
- [Network flows](src/graph/flow.rs): Dinic's blocking flow, Hopcroft-Karp bipartite matching, min cost max flow
4949
- [Connected components](src/graph/connectivity.rs): 2-edge-, 2-vertex- and strongly connected components, bridges, articulation points, topological sort, 2-SAT
50-
- [Associative range query](src/range_query): known colloquially as *segtrees*, and Mo's query square root decomposition
51-
- [GCD Math](src/math/mod.rs): canonical solution to Bezout's identity
50+
- [Associative range query](src/range_query): known colloquially as *segtrees*, coordinate compression, and Mo's query square root decomposition
51+
- [Number thery](src/math/mod.rs): canonical solution to Bezout's identity, Miller's primality test
5252
- [Arithmetic](src/math/num.rs): rational and complex numbers, linear algebra, safe modular arithmetic
5353
- [FFT](src/math/fft.rs): fast Fourier transform, number theoretic transform, convolution
5454
- [Scanner](src/scanner.rs): utility for reading input data ergonomically

‎src/range_query/mod.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,53 @@ pub use dynamic_arq::{ArqView, DynamicArq};
66
pub use specs::ArqSpec;
77
pub use static_arq::StaticArq;
88

9+
/// A simple data structure for coordinate compression
10+
pub struct SparseIndex {
11+
coords: Vec<i64>
12+
}
13+
14+
impl SparseIndex {
15+
/// Build an index, given the full set of coordinates to compress.
16+
pub fn new(mut coords: Vec<i64>) -> Self {
17+
coords.sort_unstable();
18+
coords.dedup();
19+
Self { coords }
20+
}
21+
22+
/// Return Ok(i) if the coordinate q appears at index i
23+
/// Return Err(i) if q appears between indices i-1 and i
24+
pub fn compress(&self, q: i64) -> Result<usize, usize> {
25+
self.coords.binary_search(&q)
26+
}
27+
}
28+
929
#[cfg(test)]
1030
mod test {
1131
use super::specs::*;
1232
use super::*;
1333

34+
#[test]
35+
fn test_coord_compress() {
36+
let mut coords = vec![16, 99, 45, 18];
37+
let index = SparseIndex::new(coords.clone());
38+
39+
coords.sort_unstable();
40+
for (i, q) in coords.into_iter().enumerate() {
41+
assert_eq!(index.compress(q - 1), Err(i));
42+
assert_eq!(index.compress(q), Ok(i));
43+
assert_eq!(index.compress(q + 1), Err(i + 1));
44+
}
45+
}
46+
47+
#[test]
48+
fn test_range_compress() {
49+
let queries = vec![(0, 10), (10, 19), (20, 29)];
50+
let coords = queries.iter().flat_map(|&(i, j)| vec![i, j + 1]).collect();
51+
let index = SparseIndex::new(coords);
52+
53+
assert_eq!(index.coords, vec![0, 10, 11, 20, 30]);
54+
}
55+
1456
#[test]
1557
fn test_rmq() {
1658
let mut arq = StaticArq::<AssignMin>::new(&[0; 10]);

‎src/range_query/specs.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ pub trait ArqSpec {
1515
/// Must satisfy the Identity Law:
1616
/// For all a, op(a, identity()) = op(identity(), a) = a
1717
fn identity() -> Self::S;
18-
/// For point query / eager updates, compose() can be unimplemented!()
19-
/// For range query / lazy updates, it must satisfy the Composition Law:
18+
/// Must satisfy the Composition Law:
2019
/// For all f,g,a, apply(compose(f, g), a) = apply(f, apply(g, a))
2120
fn compose(f: &Self::F, g: &Self::F) -> Self::F;
22-
/// For point query / eager updates, apply() can assume it acts on a leaf.
23-
/// For range query / lazy updates, it must satisfy the Distributive Law:
24-
/// For all f,a,b, apply(f, op(a, b)) = op(apply(f, a), apply(f, b))
21+
/// Must satisfy the Distributive Law:
22+
/// For all f,a,b, apply(f, op(a, b), s+t) = op(apply(f, a, s), apply(f, b, t))
2523
/// The `size` parameter makes this law easier to satisfy in certain cases.
2624
fn apply(f: &Self::F, a: &Self::S, size: i64) -> Self::S;
25+
26+
// The following relaxations to the laws may apply.
27+
// If only point updates are made, the Composition and Distributive Laws
28+
// no longer apply.
29+
// - compose() is never called, so it can be left unimplemented!().
30+
// - apply() is only ever called on leaves, i.e., with size == 1.
31+
// If only point queries are made, the Associative and Distributive Laws
32+
// no longer apply.
33+
// - op()'s result only matters when identity() is an argument.
34+
// - apply()'s result only matters on leaves, i.e., with size == 1.
2735
}
2836

2937
/// Range Minimum Query (RMQ), a classic application of ARQ.
@@ -109,7 +117,8 @@ impl ArqSpec for SupplyDemand {
109117
fn compose(_: &Self::F, _: &Self::F) -> Self::F {
110118
unimplemented!()
111119
}
112-
fn apply(&(p_add, o_add): &Self::F, &(p, o, _): &Self::S, _: i64) -> Self::S {
120+
fn apply(&(p_add, o_add): &Self::F, &(p, o, _): &Self::S, s: i64) -> Self::S {
121+
assert_eq!(s, 1);
113122
let p = p + p_add;
114123
let o = o + o_add;
115124
(p, o, p.min(o))

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /