use std::ops::Range;
use tinyvec::TinyVec;
#[derive(Debug, Default)]
pub struct ArrayRangeSet(TinyVec<[Range<u64>; ARRAY_RANGE_SET_INLINE_CAPACITY]>);
const ARRAY_RANGE_SET_INLINE_CAPACITY: usize = 2;
impl Clone for ArrayRangeSet {
fn clone(&self) -> Self {
if self.0.is_inline() || self.0.len() > ARRAY_RANGE_SET_INLINE_CAPACITY {
return Self(self.0.clone());
}
let mut vec = TinyVec::new();
vec.extend_from_slice(self.0.as_slice());
Self(vec)
}
}
impl ArrayRangeSet {
pub fn new() -> Self {
Default::default()
}
pub fn iter(&self) -> impl DoubleEndedIterator<Item = Range<u64>> + '_ {
self.0.iter().cloned()
}
pub fn elts(&self) -> impl Iterator<Item = u64> + '_ {
self.iter().flatten()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn contains(&self, x: u64) -> bool {
let idx = self.0.partition_point(|range| range.start <= x);
if idx == 0 {
return false;
}
self.0[idx - 1].contains(&x)
}
pub fn subtract(&mut self, other: &Self) {
for range in &other.0 {
self.remove(range.clone());
}
}
pub fn insert_one(&mut self, x: u64) -> bool {
self.insert(x..x + 1)
}
pub fn insert(&mut self, x: Range<u64>) -> bool {
let mut result = false;
if x.is_empty() {
return false;
}
let mut idx = 0;
while idx != self.0.len() {
let range = &mut self.0[idx];
if range.start > x.end {
self.0.insert(idx, x);
return true;
} else if range.start > x.start {
result = true;
range.start = x.start;
}
if x.end <= range.end {
return result;
} else if x.start <= range.end {
range.end = x.end;
while idx + 1 < self.0.len() {
let curr_end = self.0[idx].end;
let next_start = self.0[idx + 1].start;
if curr_end >= next_start {
let next_end = self.0[idx + 1].end;
self.0[idx].end = next_end.max(curr_end);
self.0.remove(idx + 1);
} else {
break;
}
}
return true;
}
idx += 1;
}
self.0.push(x);
true
}
pub fn remove(&mut self, x: Range<u64>) -> bool {
let mut result = false;
if x.is_empty() {
return false;
}
let mut idx = 0;
while idx != self.0.len() && x.start != x.end {
let range = self.0[idx].clone();
if x.end <= range.start {
return result;
} else if x.start >= range.end {
idx += 1;
continue;
}
result = true;
let left = range.start..x.start;
let right = x.end..range.end;
if left.is_empty() && right.is_empty() {
self.0.remove(idx);
} else if left.is_empty() {
self.0[idx] = right;
idx += 1;
} else if right.is_empty() {
self.0[idx] = left;
idx += 1;
} else {
self.0[idx] = right;
self.0.insert(idx, left);
idx += 2;
}
}
result
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn pop_min(&mut self) -> Option<Range<u64>> {
if !self.0.is_empty() {
Some(self.0.remove(0))
} else {
None
}
}
pub fn min(&self) -> Option<u64> {
self.iter().next().map(|x| x.start)
}
pub fn max(&self) -> Option<u64> {
self.iter().next_back().and_then(|x| x.end.checked_sub(1))
}
}