Skip to main content

LiChaoTree

Struct LiChaoTree 

Source
pub struct LiChaoTree<X, L> {
    range: Range<X>,
    nodes: Vec<LiChaoNode<X, L>>,
}

Fields§

§range: Range<X>§nodes: Vec<LiChaoNode<X, L>>

Implementations§

Source§

impl<X, L> LiChaoTree<X, L>
where X: IntBase, L: LiChaoLine<X>,

Source

pub fn new(range: Range<X>) -> Self

Source

fn push_node(&mut self, segment: LiChaoSegment<X, L>) -> u32

Examples found in repository?
crates/competitive/src/data_structure/li_chao_tree.rs (line 207)
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    }
Source

pub fn add_line(&mut self, line: L)

Source

pub fn add_segment(&mut self, range: Range<X>, line: L)

Source

fn add_segment_at( &mut self, index: u32, segment: LiChaoSegment<X, L>, left: X, right: X, )

Examples found in repository?
crates/competitive/src/data_structure/li_chao_tree.rs (lines 142-150)
141    pub fn add_line(&mut self, line: L) {
142        self.add_segment_at(
143            0,
144            LiChaoSegment {
145                range: self.range.clone(),
146                line,
147            },
148            self.range.start,
149            self.range.end,
150        );
151    }
152
153    pub fn add_segment(&mut self, range: Range<X>, line: L) {
154        assert!(self.range.start <= range.start && range.end <= self.range.end);
155        if range.start < range.end {
156            self.add_segment_at(
157                0,
158                LiChaoSegment { range, line },
159                self.range.start,
160                self.range.end,
161            );
162        }
163    }
164
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    }
Source

pub fn query_min(&self, x: X) -> Option<L::Output>

Trait Implementations§

Source§

impl<X: Clone, L: Clone> Clone for LiChaoTree<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 LiChaoTree<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 LiChaoTree<X, L>
where Range<X>: Freeze, Vec<LiChaoNode<X, L>>: Freeze,

§

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

§

impl<X, L> Send for LiChaoTree<X, L>
where Range<X>: Send, Vec<LiChaoNode<X, L>>: Send,

§

impl<X, L> Sync for LiChaoTree<X, L>
where Range<X>: Sync, Vec<LiChaoNode<X, L>>: Sync,

§

impl<X, L> Unpin for LiChaoTree<X, L>
where Range<X>: Unpin, Vec<LiChaoNode<X, L>>: Unpin,

§

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

§

impl<X, L> UnwindSafe for LiChaoTree<X, L>

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.