//IMPORTS {{{
#![allow(unused_parens)]
#![allow(unstable_name_collisions)] //`num::Integer::div_ceil()`, `num::Integer::next_multiple_of()` etc.
use std::io::{self, Read};
#[allow(unused_imports)]
use std::{
cmp::Ordering::{self, Equal, Greater, Less},
cmp::Reverse,
collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque},
f64::consts::{FRAC_PI_2, PI},
mem::swap,
rc::Rc,
sync::atomic::{AtomicUsize, Ordering::SeqCst},
time::Instant,
};
//}}}
//MACROS {{{
//input parser
#[allow(unused_macros)]
macro_rules! collect {
($v:expr) => {{
$v.collect_scalar()
}};
($v:expr, $i:expr) => {{
$v.collect_vector($i)
}};
($v:expr, $i:expr, $j: expr) => {{
$v.collect_matrix($i, $j)
}};
}
#[allow(unused_macros)]
macro_rules! collect_step {
($v:expr, $i:expr, $j: expr) => {{
$v.collect_vector_step($i, $j)
}};
}
#[allow(unused_macros)]
macro_rules! collect_seq {
($v:expr) => {{
$v.collect_sequence()
}};
}
#[allow(unused_macros)]
macro_rules! collect_special {
($v:expr, $i:expr) => {{
$v.collect_vector_special($i)
}};
}
//debug print
#[allow(unused_macros)]
macro_rules! o {
(---) => { #[cfg(test)] println!("\u{001B}[090m{}\u{001B}[0m", "―".repeat(10)) };
($expr:literal) => { #[cfg(test)] println!("{}", $expr) };
($expr:expr) => { #[cfg(test)] println!("{} = {:?}", stringify!($expr), $expr) };
($($expr:expr),*) => { #[cfg(test)] println!($($expr),*) };
}
#[allow(unused_macros)]
macro_rules! oo {
($v:expr) => {
#[cfg(test)]
{
if ($v.is_empty()) {
println!("{} = []", stringify!($v));
} else {
println!("{} = [", stringify!($v));
$v.iter().enumerate().for_each(|(i, e)| {
println!(" {:3}: {:?}", i, e);
});
println!("]");
}
}
};
}
#[allow(unused_macros)]
macro_rules! ooo {
($v:expr) => {
#[cfg(test)]
{
if ($v.is_empty()) {
println!("{} = {{}}", stringify!($v));
} else {
println!("{} = {{", stringify!($v));
$v.iter().sorted().for_each(|(k, v)| {
println!(" {:3}: {:?}", k, v);
});
println!("}}");
}
}
};
}
//map literal, set literal
#[allow(unused_macros)]
macro_rules! map {
() => {
FxHashMap::default()
};
($($key:tt : $value:tt,)+) => {
map!($($key : $value),+)
};
($($key:tt : $value:tt),+) => {
{
let mut m = FxHashMap::default();
$(
m.insert($key, $value);
)+
m
}
};
}
#[allow(unused_macros)]
macro_rules! set {
() => {
FxHashSet::default()
};
($($value:expr,)+) => {
set!($($value),+)
};
($($value:expr),+) => {
{
let mut s = FxHashSet::default();
$(
s.insert($value);
)+
s
}
};
}
//stopwatch
//Example:
// let mut start = Instant::now();
// /* do something */
// tt!(start [,
]);
// /* do something */
// tt!(start [, ]);
#[allow(unused_macros)]
macro_rules! tt {
($t:expr) => {
#[cfg(test)]
{
println!("{}ms", $t.elapsed().as_millis());
#[allow(unused_assignments)]
{
$t = Instant::now();
}
}
};
($t:expr, $title:expr) => {
#[cfg(test)]
{
println!("{}ms ({})", $t.elapsed().as_millis(), $title);
#[allow(unused_assignments)]
{
$t = Instant::now();
}
}
};
}
//cumulative time measurement for block
//Usage: `time! {{ ... }}`, then `time_print!()`
//Bug: The value may be cumulated over multiple tests. `cargo test -- --test-threads 1` can avoid it.
#[allow(dead_code)]
static ELAPSED_TIME_NS: AtomicUsize = AtomicUsize::new(0);
#[allow(unused_macros)]
macro_rules! time {
($v:block) => {{
#[cfg(test)]
let start = Instant::now();
let ret = $v;
#[cfg(test)]
ELAPSED_TIME_NS.fetch_add(start.elapsed().as_nanos() as usize, SeqCst);
ret
}};
}
#[allow(unused_macros)]
macro_rules! time_reset {
() => {{
#[cfg(test)]
ELAPSED_TIME_NS.store(0, SeqCst);
}};
}
#[allow(unused_macros)]
macro_rules! time_print {
() => {{
#[cfg(test)]
println!("{}ms", ELAPSED_TIME_NS.load(SeqCst) / 1000 / 1000);
}};
}
//}}}
/*-------------------------------------*/
/* solve */
//LazySegmentTree {{{
//遅延セグ木
//参考: |https://maspypy.com/segment-tree-%e3%81%ae%e3%81%8a%e5%8b%89%e5%bc%b71| (非遅延セグ木)
//参考: |https://maspypy.com/segment-tree-%e3%81%ae%e3%81%8a%e5%8b%89%e5%bc%b72| (遅延セグ木)
//
//問題によっては(試した限りほとんどの問題で)、この遅延セグ木はTLEするほどに遅い
//原因は、現状の実装は任意の作用に対応しており、作用の合成も可能だが、合成をする度に作用のclosureがネストされていくためである(空間計算量の問題もあるが、ネストしすぎて作用の適用自体に時間が掛かる可能性がある)
//つまり抽象化が原因であるため、「区間加算しか来ない」や「区間更新しか来ない」といったことが分かっている場合は、以下の何れかの方法で高速化が可能である
//- `self.__compose_action()`における作用の合成を最適化する(例えば区間加算の場合はclosureのネストは不要で、`+3`作用と`+5`作用であれば新しく`+8`作用を一つ作り直せば良い)
//- より速度が求められる場合は、さらに`self.action`の型を最適化すれば良い(例えば区間加算であればclosureは不要で`Vec