use super::functions::*;
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct FloatInterval {
pub(super) lo: f64,
pub(super) hi: f64,
}
impl FloatInterval {
pub fn new(lo: f64, hi: f64) -> Self {
assert!(
lo <= hi,
"FloatInterval: lo ({}) must be <= hi ({})",
lo,
hi
);
Self { lo, hi }
}
pub fn try_new(lo: f64, hi: f64) -> Option<Self> {
if lo <= hi {
Some(Self { lo, hi })
} else {
None
}
}
pub fn lo(self) -> f64 {
self.lo
}
pub fn hi(self) -> f64 {
self.hi
}
pub fn width(self) -> f64 {
self.hi - self.lo
}
pub fn midpoint(self) -> f64 {
self.lo + (self.hi - self.lo) / 2.0
}
pub fn contains(self, x: f64) -> bool {
x >= self.lo && x <= self.hi
}
pub fn add(self, other: Self) -> Self {
Self::new(self.lo + other.lo, self.hi + other.hi)
}
pub fn sub(self, other: Self) -> Self {
Self::new(self.lo - other.hi, self.hi - other.lo)
}
pub fn mul(self, other: Self) -> Self {
let products = [
self.lo * other.lo,
self.lo * other.hi,
self.hi * other.lo,
self.hi * other.hi,
];
let lo = products.iter().cloned().fold(f64::INFINITY, f64::min);
let hi = products.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
Self::new(lo, hi)
}
pub fn neg(self) -> Self {
Self::new(-self.hi, -self.lo)
}
pub fn intersect(self, other: Self) -> Option<Self> {
let lo = f64::max(self.lo, other.lo);
let hi = f64::min(self.hi, other.hi);
Self::try_new(lo, hi)
}
pub fn hull(self, other: Self) -> Self {
Self::new(f64::min(self.lo, other.lo), f64::max(self.hi, other.hi))
}
pub fn is_subset_of(self, other: Self) -> bool {
other.lo <= self.lo && self.hi <= other.hi
}
pub fn abs(self) -> Self {
if self.lo >= 0.0 {
self
} else if self.hi <= 0.0 {
self.neg()
} else {
Self::new(0.0, f64::max(-self.lo, self.hi))
}
}
pub fn square(self) -> Self {
self.mul(self)
}
pub fn mignitude(self) -> f64 {
if self.lo >= 0.0 {
self.lo
} else if self.hi <= 0.0 {
-self.hi
} else {
0.0
}
}
pub fn magnitude(self) -> f64 {
f64::max(self.lo.abs(), self.hi.abs())
}
}
#[allow(dead_code)]
pub struct RangeMinSegTree {
n: usize,
data: Vec<i64>,
}
impl RangeMinSegTree {
const INF: i64 = i64::MAX;
pub fn build(values: &[i64]) -> Self {
let n = values.len();
let mut data = vec![Self::INF; 4 * (n + 1)];
if n > 0 {
Self::build_rec(&mut data, values, 1, 0, n - 1);
}
Self { n, data }
}
fn build_rec(data: &mut Vec<i64>, values: &[i64], node: usize, lo: usize, hi: usize) {
if lo == hi {
data[node] = values[lo];
return;
}
let mid = (lo + hi) / 2;
Self::build_rec(data, values, 2 * node, lo, mid);
Self::build_rec(data, values, 2 * node + 1, mid + 1, hi);
data[node] = data[2 * node].min(data[2 * node + 1]);
}
pub fn query_min(&self, l: usize, r: usize) -> Option<i64> {
if self.n == 0 || l > r || r >= self.n {
return None;
}
Some(self.query_rec(1, 0, self.n - 1, l, r))
}
fn query_rec(&self, node: usize, lo: usize, hi: usize, l: usize, r: usize) -> i64 {
if r < lo || hi < l {
return Self::INF;
}
if l <= lo && hi <= r {
return self.data[node];
}
let mid = (lo + hi) / 2;
let left = self.query_rec(2 * node, lo, mid, l, r);
let right = self.query_rec(2 * node + 1, mid + 1, hi, l, r);
left.min(right)
}
pub fn update(&mut self, i: usize, val: i64) {
if i < self.n {
self.update_rec(1, 0, self.n - 1, i, val);
}
}
fn update_rec(&mut self, node: usize, lo: usize, hi: usize, i: usize, val: i64) {
if lo == hi {
self.data[node] = val;
return;
}
let mid = (lo + hi) / 2;
if i <= mid {
self.update_rec(2 * node, lo, mid, i, val);
} else {
self.update_rec(2 * node + 1, mid + 1, hi, i, val);
}
self.data[node] = self.data[2 * node].min(self.data[2 * node + 1]);
}
pub fn len(&self) -> usize {
self.n
}
pub fn is_empty(&self) -> bool {
self.n == 0
}
}
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct ValidatedInterval {
interval: FloatInterval,
certificate: String,
is_verified: bool,
}
impl ValidatedInterval {
pub fn verified(interval: FloatInterval, certificate: impl Into<String>) -> Self {
Self {
interval,
certificate: certificate.into(),
is_verified: true,
}
}
pub fn unverified(interval: FloatInterval) -> Self {
Self {
interval,
certificate: String::new(),
is_verified: false,
}
}
pub fn interval(&self) -> FloatInterval {
self.interval
}
pub fn is_verified(&self) -> bool {
self.is_verified
}
pub fn certificate(&self) -> &str {
&self.certificate
}
pub fn add(&self, other: &Self) -> Self {
Self {
interval: self.interval.add(other.interval),
certificate: format!("add({}, {})", self.certificate, other.certificate),
is_verified: self.is_verified && other.is_verified,
}
}
pub fn mul(&self, other: &Self) -> Self {
Self {
interval: self.interval.mul(other.interval),
certificate: format!("mul({}, {})", self.certificate, other.certificate),
is_verified: self.is_verified && other.is_verified,
}
}
}
#[allow(dead_code)]
pub struct IntervalScheduler {
jobs: Vec<ScheduledJob>,
}
impl IntervalScheduler {
pub fn new(jobs: Vec<ScheduledJob>) -> Self {
Self { jobs }
}
fn latest_compatible(&self, idx: usize) -> Option<usize> {
let start = self.jobs[idx].start;
let mut result = None;
for i in 0..idx {
if self.jobs[i].finish <= start {
result = Some(i);
}
}
result
}
pub fn max_weight_schedule(&mut self) -> u64 {
self.jobs.sort_by_key(|j| j.finish);
let n = self.jobs.len();
if n == 0 {
return 0;
}
let mut dp = vec![0u64; n + 1];
for i in 0..n {
let weight = self.jobs[i].weight;
let p = self.latest_compatible(i).map(|j| j + 1).unwrap_or(0);
dp[i + 1] = dp[i].max(dp[p] + weight);
}
dp[n]
}
pub fn job_count(&self) -> usize {
self.jobs.len()
}
}
#[allow(dead_code)]
pub struct KrawczykSolver {
max_iters: usize,
tolerance: f64,
}
impl KrawczykSolver {
pub fn new(max_iters: usize, tolerance: f64) -> Self {
Self {
max_iters,
tolerance,
}
}
pub fn solve<F, DF>(&self, mut x: FloatInterval, f: F, df: DF) -> Option<FloatInterval>
where
F: Fn(f64) -> f64,
DF: Fn(FloatInterval) -> FloatInterval,
{
for _ in 0..self.max_iters {
let m = x.midpoint();
let fm = f(m);
let dfx = df(x);
if dfx.mignitude() < 1e-15 {
return None;
}
let (lo, hi) = if dfx.lo > 0.0 {
(m - fm / dfx.lo, m - fm / dfx.hi)
} else if dfx.hi < 0.0 {
(m - fm / dfx.hi, m - fm / dfx.lo)
} else {
return None;
};
let k = FloatInterval::try_new(lo, hi)?;
let next = k.intersect(x)?;
if next.width() < self.tolerance {
return Some(next);
}
x = next;
}
None
}
}
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct ScheduledJob {
pub id: usize,
pub start: u64,
pub finish: u64,
pub weight: u64,
}
impl ScheduledJob {
pub fn new(id: usize, start: u64, finish: u64, weight: u64) -> Self {
Self {
id,
start,
finish,
weight,
}
}
pub fn overlaps(&self, other: &Self) -> bool {
self.start < other.finish && other.start < self.finish
}
pub fn compatible(&self, other: &Self) -> bool {
!self.overlaps(other)
}
}