1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
//! 区間和の二分探索に関するトレイトたち。
//!
//! 区間のモノイド積が述語を満たすような区間のうち、最大のものを返す。
use super::binop;
use super::fold;
use std::ops::Range;
use binop::Magma;
use fold::Fold;
/// 左端を固定したときの境界を求める。
pub trait FoldBisect: Fold<Range<usize>> {
/// 添字 `l` と述語 `pred` を引数に取り、次の条件を満たす `r` を返す。
/// ただし、区間長を `n` とする。
/// - `pred(&self.fold(l..r))`
/// - `r == n || !pred(&self.fold(l..r + 1))`
///
/// # Requirements
/// 対象のモノイドの単位元を `e` とするとき、 `pred(e)` が成り立つ。
///
/// # Examples
/// ```
/// use nekolib::ds::VecSegtree;
/// use nekolib::traits::{Fold, FoldBisect};
/// use nekolib::utils::OpAdd;
///
/// let vs: VecSegtree<OpAdd<i32>> = vec![2, 4, 1, 3, 5].into();
///
/// assert_eq!(vs.fold_bisect(1, |&x| x < 4), (1_usize, 0));
/// assert_eq!(vs.fold_bisect(1, |&x| x <= 4), (2_usize, 4));
/// assert_eq!(vs.fold_bisect(1, |&x| x < 13), (4_usize, 8));
/// assert_eq!(vs.fold_bisect(1, |&x| x <= 13), (5_usize, 13));
///
/// let l = 1;
/// let pred = |&x: &i32| x <= 12;
/// let (r, x) = vs.fold_bisect(l, pred);
/// assert_eq!(vs.fold(l..r), x);
/// assert!(pred(&x));
/// assert!(r == vs.len() || !pred(&vs.fold(l..r + 1)));
/// ```
fn fold_bisect<F>(
&self,
l: usize,
pred: F,
) -> (usize, <Self::Output as Magma>::Set)
where
F: Fn(&<Self::Output as Magma>::Set) -> bool;
}
/// 右端を固定したときの境界を求める。
pub trait FoldBisectRev: Fold<Range<usize>> {
/// 添字 `r` と述語 `pred` を引数に取り、次の条件を満たす `l` を返す。
/// - `pred(&self.fold(l..r))`
/// - `l == 0 || !pred(&self.fold(l - 1..r))`
///
/// # Requirements
/// 対象のモノイドの単位元を `e` とするとき、`pred(e)` が成り立つ。
///
/// # Examples
/// ```
/// use nekolib::ds::VecSegtree;
/// use nekolib::traits::{Fold, FoldBisectRev};
/// use nekolib::utils::OpAdd;
///
/// let vs: VecSegtree<OpAdd<i32>> = vec![2, 4, 1, 3, 5].into();
///
/// assert_eq!(vs.fold(..), 15);
/// assert_eq!(vs.fold_bisect_rev(5, |&x| x <= 0), (5_usize, 0));
/// assert_eq!(vs.fold_bisect_rev(5, |&x| x < 15), (1_usize, 13));
/// assert_eq!(vs.fold_bisect_rev(5, |&x| x <= 15), (0_usize, 15));
///
/// let r = 5;
/// let pred = |&x: &i32| x <= 12;
/// let (l, x) = vs.fold_bisect_rev(r, pred);
/// assert_eq!(vs.fold(l..r), x);
/// assert!(pred(&x));
/// assert!(l == 0 || !pred(&vs.fold(l - 1..r)));
/// ```
fn fold_bisect_rev<F>(
&self,
r: usize,
pred: F,
) -> (usize, <Self::Output as Magma>::Set)
where
F: Fn(&<Self::Output as Magma>::Set) -> bool;
}