use core::ops::RangeBounds;
use crate::{BTree, BTreeTrait, HeapVec, MutElemArrSlice, NodePath, QueryResult};
pub trait Sliceable<T = usize>: HasLength<T> {
#[must_use]
fn slice(&self, range: impl RangeBounds<T>) -> Self;
fn slice_(&mut self, range: impl RangeBounds<T>)
where
Self: Sized,
{
*self = self.slice(range);
}
}
pub trait Mergeable {
fn can_merge(&self, rhs: &Self) -> bool;
fn merge_right(&mut self, rhs: &Self);
fn merge_left(&mut self, left: &Self);
}
pub trait HasLength<T = usize> {
fn rle_len(&self) -> T;
}
impl<T: Mergeable, B: BTreeTrait<Elem = T>> BTree<B> {
pub fn get_mergeable_num(&self) -> usize {
let mut last: Option<&T> = None;
let mut num = 0;
for span in self.iter() {
match &mut last {
Some(last) => {
num += if last.can_merge(span) { 1 } else { 0 };
}
None => last = Some(span),
}
}
num
}
pub fn try_merge_to_neighbors(&mut self, start: QueryResult, end: QueryResult) {
todo!()
}
fn try_merge_next(&mut self, path: NodePath) -> bool {
let leaf_idx = path.last().unwrap();
let leaf = self.get_node(leaf_idx.arena);
if leaf.is_lack() {
self.handle_lack(path.last().unwrap().arena);
return true;
}
let mut sibling_path = path.clone();
if !self.next_sibling(&mut sibling_path) {
return false;
}
let next_idx = sibling_path.last().unwrap();
let next = self.get_node(next_idx.arena);
if next.is_lack() {
self.handle_lack(sibling_path.last().unwrap().arena);
return true;
}
if leaf
.elements
.last()
.unwrap()
.can_merge(next.elements.first().unwrap())
{
let (a, b) = self.get2_mut(leaf_idx.arena, next_idx.arena);
while a
.elements
.last()
.map(|x| x.can_merge(b.elements.first().unwrap()))
.unwrap_or(false)
{
let last = a.elements.pop().unwrap();
b.elements[0].merge_left(&last);
}
if a.is_lack() {
self.handle_lack(path.last().unwrap().arena);
return true;
}
}
false
}
fn try_merge_prev(&mut self, path: NodePath) -> bool {
let mut sibling_path = path;
if !self.prev_sibling(&mut sibling_path) {
return false;
}
self.try_merge_next(sibling_path)
}
}
pub fn delete_range_in_elements<T: Sliceable>(
elements: &mut HeapVec<T>,
start: Option<QueryResult>,
end: Option<QueryResult>,
) -> Vec<T> {
match (&start, &end) {
(Some(from), Some(to)) if from.elem_index == to.elem_index => {
if from.elem_index >= elements.len() {
assert!(!from.found);
return Vec::new();
}
let mut ans = Vec::new();
let elem = &mut elements[from.elem_index];
ans.push(elem.slice(from.offset..to.offset));
if to.offset != elem.rle_len() {
if from.offset == 0 {
elements[from.elem_index].slice_(to.offset..);
} else {
let right = elements[from.elem_index].slice(to.offset..);
elements[from.elem_index].slice_(..from.offset);
elements.insert(from.elem_index + 1, right);
}
} else if from.offset == 0 {
elements.remove(from.elem_index);
} else {
elements[from.elem_index].slice_(to.offset..);
}
return ans;
}
_ => {}
}
let mut ans: Vec<T> = Vec::new();
let start_index = match &start {
Some(start) => {
if start.offset == 0 {
start.elem_index
} else if start.offset == elements[start.elem_index].rle_len() {
start.elem_index + 1
} else {
let elem = &mut elements[start.elem_index];
ans.push(elem.slice(start.offset..));
elem.slice_(..start.offset);
start.elem_index + 1
}
}
None => 0,
};
match &end {
Some(end) if end.elem_index < elements.len() => {
if end.offset == elements[end.elem_index].rle_len() {
ans.extend(elements.drain(start_index..end.elem_index + 1));
} else if end.offset != 0 {
ans.extend(elements.drain(start_index..end.elem_index));
let elem = &mut elements[start_index];
ans.push(elem.slice(..end.offset));
elem.slice_(end.offset..);
} else {
ans.extend(elements.drain(start_index..end.elem_index));
}
}
_ => {
ans.extend(elements.drain(start_index..));
}
};
ans
}
pub fn update_slice<T: Sliceable, F>(slice: &mut MutElemArrSlice<T>, f: &mut F) -> bool
where
F: FnMut(&mut T) -> bool,
{
let mut should_update = false;
match (slice.start, slice.end) {
(Some((start_index, start_offset)), Some((end_index, end_offset)))
if start_index == end_index =>
{
if start_offset > 0 {
if end_offset < slice.elements[start_index].rle_len() {
let mut elem = slice.elements[start_index].slice(start_offset..end_offset);
should_update = should_update || f(&mut elem);
let right = slice.elements[start_index].slice(end_offset..);
slice.elements[start_index].slice_(..start_offset);
slice
.elements
.splice(start_index + 1..start_index + 1, [elem, right]);
} else {
let mut elem = slice.elements[start_index].slice(start_offset..end_offset);
should_update = should_update || f(&mut elem);
slice.elements[start_index].slice_(..start_offset);
slice.elements.insert(start_index + 1, elem);
}
} else if end_offset < slice.elements[start_index].rle_len() {
let mut elem = slice.elements[start_index].slice(..end_offset);
should_update = should_update || f(&mut elem);
slice.elements[start_index].slice_(end_offset..);
slice.elements.insert(start_index, elem);
} else {
should_update = should_update || f(&mut slice.elements[start_index]);
}
return should_update;
}
_ => {}
};
let mut shift = 0;
let start = match slice.start {
Some((start_index, start_offset)) => {
if start_offset == 0
|| start_index == slice.elements.len()
|| slice.elements[start_index].rle_len() == 0
{
start_index
} else if start_offset == slice.elements[start_index].rle_len() {
start_index + 1
} else {
let elem = slice.elements[start_index].slice(start_offset..);
slice.elements[start_index].slice_(..start_offset);
slice.elements.insert(start_index + 1, elem);
shift = 1;
start_index + 1
}
}
None => 0,
};
let end = match slice.end {
Some((end_index, end_offset)) if end_index + shift < slice.elements.len() => {
let origin = &mut slice.elements[end_index + shift];
if end_offset == origin.rle_len() || origin.rle_len() == 0 {
end_index + 1 + shift
} else if end_offset == 0 {
end_index + shift
} else {
let elem = origin.slice(..end_offset);
origin.slice_(end_offset..);
slice.elements.insert(end_index + shift, elem);
shift += 1;
end_index + shift
}
}
_ => slice.elements.len(),
};
let mut ans = false;
for elem in slice.elements[start..end].iter_mut() {
ans = f(elem) || ans;
}
ans
}
pub fn scan_and_merge<T: Mergeable>(elements: &mut HeapVec<T>, start: usize) {
if start + 1 >= elements.len() {
return;
}
let (left, right) = elements.split_at_mut(start + 1);
let start_elem = left.last_mut().unwrap();
let mut i = 0;
while i < right.len() {
if !start_elem.can_merge(&right[i]) {
break;
}
start_elem.merge_right(&right[i]);
i += 1;
}
if i > 0 {
elements.drain(start + 1..start + 1 + i);
}
}
pub fn insert_with_split<T: Sliceable + Mergeable>(
elements: &mut HeapVec<T>,
index: usize,
offset: usize,
elem: T,
) {
if elements.is_empty() {
elements.push(elem);
return;
}
if index == elements.len() {
debug_assert_eq!(offset, 0);
let last = elements.last_mut().unwrap();
if last.can_merge(&elem) {
last.merge_right(&elem);
} else {
elements.push(elem);
}
return;
}
assert!(index < elements.len());
if offset == 0 {
let target = elements.get_mut(index).unwrap();
if elem.can_merge(target) {
target.merge_left(&elem);
} else {
elements.insert(index, elem);
}
} else if offset == elements[index].rle_len() {
let target = elements.get_mut(index).unwrap();
if target.can_merge(&elem) {
target.merge_right(&elem);
} else {
elements.insert(index + 1, elem);
}
} else {
let right = elements[index].slice(offset..);
elements[index].slice_(..offset);
let left = elements.get_mut(index).unwrap();
if left.can_merge(&elem) {
left.merge_right(&elem);
elements.insert(index + 1, right);
} else {
elements.splice(index + 1..index + 1, [elem, right]);
}
}
}