Struct nekolib::math::SlopeFunction

source ·
pub struct SlopeFunction<I: Ord> { /* private fields */ }
Expand description

区分線形凸関数。

整数の多重集合 $L$, $R$ に対して、次の形で表せる関数を管理する: $$ f(x) = c + \sum_{l\in L} (l-x)_+ + \sum_{r\in R} (x-r)_+. $$ ここで、$(a-x)_+ = \max\{0, a-x\}$、$(x-a)_+ = \max\{0, x-a\}$ とする。 たとえば、$|x-a| = (a-x)_+ + (x-a)_+$ と書ける。

Idea

todo!()

Complexity

演算時間計算量
new$O(1)$
add_const$O(1)$
add_left, add_right, add_abs$O(\log(|L|) + \log(|R|))$
min_left, min_rightamortized $O(1)$
shift, window$O(1)$
min, argmin$O(1)$

Examples

use std::ops::Bound::{Included, Unbounded};

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_left(-1);
sf.add_left(3);
sf.add_right(2);
sf.add_const(-10);
// f(x) = 0.max(-1-x) + 0.max(3-x) + 0.max(x-2) - 10
//   x  | -5 -4 -3 -2 -1  0  1  2  3  4  5
// f(x) |  2  0 -2 -4 -6 -7 -8 -9 -9 -8 -7
assert_eq!(sf.min(), -9);
assert_eq!(sf.argmin(), (Included(2), Included(3)));

Notes

$(a_1, a_2, \dots, a_n)$ の中央値を $a_{\text{med}}$ とすると、 $\sum_{i=1}^n |x-a_i|$ は $x = a_{\text{med}}$ のとき最小となる。 このことから、値の追加と中央値を求めるクエリを処理できる。

use std::ops::Bound::{Included, Excluded, Unbounded};

use nekolib::math::SlopeFunction;

#[derive(Clone, Default)]
struct IncrementalMedian(SlopeFunction<i32>);

impl IncrementalMedian {
    fn new() -> Self { Self::default() }
    fn insert(&mut self, a: i32) { self.0.add_abs(a); }
    fn median(&self) -> Option<i32> {
        match self.0.argmin().0 {
            Included(x) => Some(x),
            Excluded(_) => unreachable!(),
            Unbounded => None,
        }
    }
}

let mut im = IncrementalMedian::new();
assert_eq!(im.median(), None); // {{}}
im.insert(2);
assert_eq!(im.median(), Some(2)); // {{2}}
im.insert(3);
assert_eq!(im.median(), Some(2)); // {{2, 3}}
im.insert(1);
assert_eq!(im.median(), Some(2)); // {{1, 2, 3}}
im.insert(1);
assert_eq!(im.median(), Some(1)); // {{1, 1, 2, 3}}

References

Implementations§

source§

impl<I: SlopeTrickInt> SlopeFunction<I>

source

pub fn new() -> Self

$f(x) = 0$ で初期化する。

Examples
use std::ops::Bound::Unbounded;

use nekolib::math::SlopeFunction;

let sf = SlopeFunction::<i32>::new();
assert_eq!(sf.min(), 0);
assert_eq!(sf.argmin(), (Unbounded, Unbounded));
source

pub fn add_const(&mut self, c: I)

$f(x) \xleftarrow{+} c$ で更新する。

Examples
use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
assert_eq!(sf.min(), 0);
sf.add_const(3);
assert_eq!(sf.min(), 3);
sf.add_const(-1);
assert_eq!(sf.min(), 2);
source

pub fn add_left(&mut self, l: I)

$f(x) \xleftarrow{+} (l-x)_+$ で更新する。

Examples
use std::ops::Bound::{Included, Unbounded};

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_left(4);
assert_eq!(sf.argmin(), (Included(4), Unbounded));
source

pub fn add_right(&mut self, r: I)

$f(x) \xleftarrow{+} (x-r)_+$ で更新する。

Examples
use std::ops::Bound::{Included, Unbounded};

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_right(4);
assert_eq!(sf.argmin(), (Unbounded, Included(4)));
source

pub fn add_abs(&mut self, a: I)

$f(x) \xleftarrow{+} |x-a|$ で更新する。

Examples
use std::ops::Bound::Included;

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
assert_eq!(sf.argmin(), (Included(4), Included(4)));
source

pub fn min_left(&mut self)

$g(x) = \min_{y\le x} f(y)$ として、$f\gets g$ で更新する。

Examples
use std::ops::Bound::{Included, Unbounded};

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
assert_eq!(sf.argmin(), (Included(4), Included(4)));
sf.min_left();
assert_eq!(sf.argmin(), (Included(4), Unbounded));
source

pub fn min_right(&mut self)

$g(x) = \min_{y\ge x} f(y)$ として、$f\gets g$ で更新する。

Examples
use std::ops::Bound::{Included, Unbounded};

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
assert_eq!(sf.argmin(), (Included(4), Included(4)));
sf.min_right();
assert_eq!(sf.argmin(), (Unbounded, Included(4)));
source

pub fn shift(&mut self, s: I)

$g(x) = f(x-a)$ として、$f\gets g$ で更新する。

Examples
use std::ops::Bound::Included;

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
assert_eq!(sf.argmin(), (Included(4), Included(4)));
sf.shift(2);
assert_eq!(sf.argmin(), (Included(6), Included(6)));
source

pub fn window(&mut self, window: RangeInclusive<I>)

$[a, b]$ に対して $g(x) = \min_{y\in[x-b, x-a]} f(y)$ として、$f\gets g$ で更新する。

Examples
use std::ops::Bound::Included;

use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
assert_eq!(sf.argmin(), (Included(4), Included(4)));
sf.window(-1..=2);
assert_eq!(sf.argmin(), (Included(3), Included(6)));
source

pub fn min(&self) -> I

$\min_{x\in\mathbb{R}} f(x)$ を返す。

Examples
use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
sf.add_const(1);
assert_eq!(sf.min(), 1);
source

pub fn argmin(&self) -> (Bound<I>, Bound<I>)

$\argmin_{x\in\mathbb{R}} f(x)$ を返す。

Examples
use std::ops::Bound::Included;
use nekolib::math::SlopeFunction;

let mut sf = SlopeFunction::new();
sf.add_abs(4);
sf.add_const(1);
assert_eq!(sf.argmin(), (Included(4), Included(4)));

Trait Implementations§

source§

impl<I: Clone + Ord> Clone for SlopeFunction<I>

source§

fn clone(&self) -> SlopeFunction<I>

Returns a copy of the value. Read more
1.0.0 · source§

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

Performs copy-assignment from source. Read more
source§

impl<I: Debug + Ord> Debug for SlopeFunction<I>

source§

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

Formats the value using the given formatter. Read more
source§

impl<I: Default + Ord> Default for SlopeFunction<I>

source§

fn default() -> SlopeFunction<I>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<I> RefUnwindSafe for SlopeFunction<I>where I: RefUnwindSafe,

§

impl<I> Send for SlopeFunction<I>where I: Send,

§

impl<I> Sync for SlopeFunction<I>where I: Sync,

§

impl<I> Unpin for SlopeFunction<I>where I: Unpin,

§

impl<I> UnwindSafe for SlopeFunction<I>where I: UnwindSafe,

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. 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 Twhere 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> ToOwned for Twhere T: Clone,

§

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 Twhere U: Into<T>,

§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

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

§

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.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V