struct LiChaoSegment<X, L> {
range: Range<X>,
line: L,
}Fields§
§range: Range<X>§line: LImplementations§
Source§impl<X, L> LiChaoSegment<X, L>
impl<X, L> LiChaoSegment<X, L>
Sourcefn evaluate(&self, x: X) -> L::Output
fn evaluate(&self, x: X) -> L::Output
Examples found in repository?
crates/competitive/src/data_structure/li_chao_tree.rs (line 217)
165 fn add_segment_at(
166 &mut self,
167 mut index: u32,
168 mut segment: LiChaoSegment<X, L>,
169 mut left: X,
170 mut right: X,
171 ) {
172 loop {
173 let last = right - X::one();
174 let middle = if left == last {
175 left
176 } else {
177 left.midpoint(last).min(last - X::one())
178 };
179 let split = middle + X::one();
180 if self.nodes[index as usize].segment.covers(left, right) && segment.covers(left, right)
181 {
182 let candidate_left = segment.line.evaluate(left);
183 let candidate_right = segment.line.evaluate(last);
184 let child = match place_line(
185 &mut self.nodes[index as usize].segment.line,
186 &mut segment.line,
187 left,
188 middle,
189 last,
190 candidate_left,
191 candidate_right,
192 ) {
193 None => return,
194 Some((Branch::Left, _, _)) => {
195 right = split;
196 segment.range.end = right;
197 0
198 }
199 Some((Branch::Right, _, _)) => {
200 left = split;
201 segment.range.start = left;
202 1
203 }
204 };
205 let next = self.nodes[index as usize].children[child];
206 if next == !0 {
207 let next = self.push_node(segment);
208 self.nodes[index as usize].children[child] = next;
209 return;
210 }
211 index = next;
212 continue;
213 }
214 let segment_right = segment.range.end - X::one();
215 if self.nodes[index as usize]
216 .segment
217 .evaluate(segment.range.start)
218 <= segment.line.evaluate(segment.range.start)
219 && self.nodes[index as usize].segment.evaluate(segment_right)
220 <= segment.line.evaluate(segment_right)
221 {
222 return;
223 }
224 let current = &self.nodes[index as usize].segment;
225 let current_left = current.range.start;
226 let current_right = current.range.end - X::one();
227 if current.line.evaluate(current_left) >= segment.evaluate(current_left)
228 && current.line.evaluate(current_right) >= segment.evaluate(current_right)
229 {
230 self.nodes[index as usize].segment = segment;
231 return;
232 }
233 if segment.covers(left, right) {
234 swap(&mut self.nodes[index as usize].segment, &mut segment);
235 }
236 let child;
237 if segment.range.end <= split {
238 child = 0;
239 right = split;
240 } else if middle < segment.range.start {
241 child = 1;
242 left = split;
243 } else {
244 let right_segment = LiChaoSegment {
245 range: split..segment.range.end,
246 line: segment.line,
247 };
248 segment.range.end = split;
249 let next = self.nodes[index as usize].children[0];
250 if next == !0 {
251 let next = self.push_node(segment);
252 self.nodes[index as usize].children[0] = next;
253 } else {
254 self.add_segment_at(next, segment, left, split);
255 }
256 let next = self.nodes[index as usize].children[1];
257 if next == !0 {
258 let next = self.push_node(right_segment);
259 self.nodes[index as usize].children[1] = next;
260 } else {
261 self.add_segment_at(next, right_segment, split, right);
262 }
263 return;
264 }
265 let next = self.nodes[index as usize].children[child];
266 if next == !0 {
267 let next = self.push_node(segment);
268 self.nodes[index as usize].children[child] = next;
269 return;
270 }
271 index = next;
272 }
273 }
274
275 pub fn query_min(&self, x: X) -> Option<L::Output> {
276 assert!(self.range.contains(&x));
277 let infinity = L::infinity().evaluate(x);
278 let mut result = infinity;
279 let (mut index, mut left, mut right) = (0, self.range.start, self.range.end);
280 while index != !0 {
281 let node = &self.nodes[index as usize];
282 result = result.min(node.segment.evaluate(x));
283 let last = right - X::one();
284 let middle = if left == last {
285 left
286 } else {
287 left.midpoint(last).min(last - X::one())
288 };
289 let split = middle + X::one();
290 if x <= middle {
291 index = node.children[0];
292 right = split;
293 } else {
294 index = node.children[1];
295 left = split;
296 }
297 }
298 (result != infinity).then_some(result)
299 }Sourcefn covers(&self, left: X, right: X) -> bool
fn covers(&self, left: X, right: X) -> bool
Examples found in repository?
crates/competitive/src/data_structure/li_chao_tree.rs (line 180)
165 fn add_segment_at(
166 &mut self,
167 mut index: u32,
168 mut segment: LiChaoSegment<X, L>,
169 mut left: X,
170 mut right: X,
171 ) {
172 loop {
173 let last = right - X::one();
174 let middle = if left == last {
175 left
176 } else {
177 left.midpoint(last).min(last - X::one())
178 };
179 let split = middle + X::one();
180 if self.nodes[index as usize].segment.covers(left, right) && segment.covers(left, right)
181 {
182 let candidate_left = segment.line.evaluate(left);
183 let candidate_right = segment.line.evaluate(last);
184 let child = match place_line(
185 &mut self.nodes[index as usize].segment.line,
186 &mut segment.line,
187 left,
188 middle,
189 last,
190 candidate_left,
191 candidate_right,
192 ) {
193 None => return,
194 Some((Branch::Left, _, _)) => {
195 right = split;
196 segment.range.end = right;
197 0
198 }
199 Some((Branch::Right, _, _)) => {
200 left = split;
201 segment.range.start = left;
202 1
203 }
204 };
205 let next = self.nodes[index as usize].children[child];
206 if next == !0 {
207 let next = self.push_node(segment);
208 self.nodes[index as usize].children[child] = next;
209 return;
210 }
211 index = next;
212 continue;
213 }
214 let segment_right = segment.range.end - X::one();
215 if self.nodes[index as usize]
216 .segment
217 .evaluate(segment.range.start)
218 <= segment.line.evaluate(segment.range.start)
219 && self.nodes[index as usize].segment.evaluate(segment_right)
220 <= segment.line.evaluate(segment_right)
221 {
222 return;
223 }
224 let current = &self.nodes[index as usize].segment;
225 let current_left = current.range.start;
226 let current_right = current.range.end - X::one();
227 if current.line.evaluate(current_left) >= segment.evaluate(current_left)
228 && current.line.evaluate(current_right) >= segment.evaluate(current_right)
229 {
230 self.nodes[index as usize].segment = segment;
231 return;
232 }
233 if segment.covers(left, right) {
234 swap(&mut self.nodes[index as usize].segment, &mut segment);
235 }
236 let child;
237 if segment.range.end <= split {
238 child = 0;
239 right = split;
240 } else if middle < segment.range.start {
241 child = 1;
242 left = split;
243 } else {
244 let right_segment = LiChaoSegment {
245 range: split..segment.range.end,
246 line: segment.line,
247 };
248 segment.range.end = split;
249 let next = self.nodes[index as usize].children[0];
250 if next == !0 {
251 let next = self.push_node(segment);
252 self.nodes[index as usize].children[0] = next;
253 } else {
254 self.add_segment_at(next, segment, left, split);
255 }
256 let next = self.nodes[index as usize].children[1];
257 if next == !0 {
258 let next = self.push_node(right_segment);
259 self.nodes[index as usize].children[1] = next;
260 } else {
261 self.add_segment_at(next, right_segment, split, right);
262 }
263 return;
264 }
265 let next = self.nodes[index as usize].children[child];
266 if next == !0 {
267 let next = self.push_node(segment);
268 self.nodes[index as usize].children[child] = next;
269 return;
270 }
271 index = next;
272 }
273 }Trait Implementations§
Auto Trait Implementations§
impl<X, L> Freeze for LiChaoSegment<X, L>
impl<X, L> RefUnwindSafe for LiChaoSegment<X, L>
impl<X, L> Send for LiChaoSegment<X, L>
impl<X, L> Sync for LiChaoSegment<X, L>
impl<X, L> Unpin for LiChaoSegment<X, L>
impl<X, L> UnsafeUnpin for LiChaoSegment<X, L>
impl<X, L> UnwindSafe for LiChaoSegment<X, L>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more