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 2cab263

Browse files
committed
Shell of convex hull algorithm
Inspired by today's Hacker Cup problem, Log Drivin' Hirin'
1 parent 0421fb0 commit 2cab263

File tree

1 file changed

+57
-5
lines changed

1 file changed

+57
-5
lines changed

‎src/range_query/sqrt_decomp.rs

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
//! A generic implementation of Mo's algorithm, aka Query Sqrt Decomposition.
2-
//! It answers q offline queries over intervals in 0..n by shifting the query
3-
//! interval's endpoints by one position at a time.
4-
//! Each endpoint incurs a total cost of at most n * sqrt(q * L_OP * R_OP).
5-
1+
/// A generic implementation of Mo's algorithm, aka Query Sqrt Decomposition.
2+
/// It answers q offline queries over intervals in 0..n by shifting the query
3+
/// interval's endpoints by one position at a time.
4+
/// Each endpoint incurs a total cost of at most n * sqrt(q * L_OP * R_OP).
65
pub trait MoState {
76
type Q;
87
type A;
@@ -102,6 +101,53 @@ impl MoState for DistinctVals {
102101
}
103102
}
104103

104+
/// Represents a minimum (lower envelope) of a collection of linear functions of a variable,
105+
/// evaluated using the convex hull trick with square root decomposition.
106+
pub struct PiecewiseLinearFn {
107+
sorted_lines: Vec<(i64, i64)>,
108+
recent_lines: Vec<(i64, i64)>,
109+
merge_threshold: usize,
110+
}
111+
112+
impl PiecewiseLinearFn {
113+
/// For N inserts interleaved with Q queries, a threshold of N/sqrt(Q) yields
114+
/// O(N sqrt Q + Q log N) time complexity. If all queries come after all inserts,
115+
/// a threshold of 0 yields O(N + Q log N) time complexity.
116+
pub fn with_merge_threshold(merge_threshold: usize) -> Self {
117+
Self {
118+
sorted_lines: vec![],
119+
recent_lines: vec![],
120+
merge_threshold,
121+
}
122+
}
123+
124+
/// Replaces this function with the minimum of itself and a provided line
125+
pub fn min_with(&mut self, slope: i64, intercept: i64) {
126+
self.recent_lines.push((slope, intercept));
127+
}
128+
129+
fn update_envelope(&mut self) {
130+
self.recent_lines.extend(self.sorted_lines.drain(..));
131+
self.recent_lines.sort_unstable();
132+
for (slope, intercept) in self.recent_lines.drain(..) {
133+
// TODO: do convex hull trick algorithm
134+
self.sorted_lines.push((slope, intercept));
135+
}
136+
}
137+
138+
fn eval_helper(&self, x: i64) -> i64 {
139+
0 // TODO: pick actual minimum, or infinity if empty
140+
}
141+
142+
/// Evaluates the function at x
143+
pub fn evaluate(&mut self, x: i64) -> i64 {
144+
if self.recent_lines.len() > self.merge_threshold {
145+
self.update_envelope();
146+
}
147+
self.eval_helper(x)
148+
}
149+
}
150+
105151
#[cfg(test)]
106152
mod test {
107153
use super::*;
@@ -115,4 +161,10 @@ mod test {
115161

116162
assert_eq!(answers, vec![2, 1, 5, 5]);
117163
}
164+
165+
#[test]
166+
fn test_convex_hull_trick() {
167+
let mut func = PiecewiseLinearFn::with_merge_threshold(3);
168+
// TODO: make test
169+
}
118170
}

0 commit comments

Comments
(0)

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