Skip to main content

LiChaoSegment

Struct LiChaoSegment 

Source
struct LiChaoSegment<X, L> {
    range: Range<X>,
    line: L,
}

Fields§

§range: Range<X>§line: L

Implementations§

Source§

impl<X, L> LiChaoSegment<X, L>
where X: Copy + Ord, L: LiChaoLine<X>,

Source

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    }
Source

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§

Source§

impl<X: Clone, L: Clone> Clone for LiChaoSegment<X, L>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<X: Debug, L: Debug> Debug for LiChaoSegment<X, L>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<X, L> Freeze for LiChaoSegment<X, L>
where Range<X>: Freeze, L: Freeze,

§

impl<X, L> RefUnwindSafe for LiChaoSegment<X, L>

§

impl<X, L> Send for LiChaoSegment<X, L>
where Range<X>: Send, L: Send,

§

impl<X, L> Sync for LiChaoSegment<X, L>
where Range<X>: Sync, L: Sync,

§

impl<X, L> Unpin for LiChaoSegment<X, L>
where Range<X>: Unpin, L: Unpin,

§

impl<X, L> UnsafeUnpin for LiChaoSegment<X, L>

§

impl<X, L> UnwindSafe for LiChaoSegment<X, L>
where Range<X>: UnwindSafe, L: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.