結果
| 問題 |
No.901 K-ary εxtrεεmε
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-10-14 20:07:30 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 280 ms / 3,000 ms |
| コード長 | 27,504 bytes |
| コンパイル時間 | 15,192 ms |
| コンパイル使用メモリ | 379,516 KB |
| 実行使用メモリ | 51,844 KB |
| 最終ジャッジ日時 | 2024-10-14 20:07:58 |
| 合計ジャッジ時間 | 22,307 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 29 |
コンパイルメッセージ
warning: field `size` is never read
--> src/main.rs:382:13
|
381 | pub struct HLD {
| --- field in this struct
382 | size: usize,
| ^^^^
|
= note: `HLD` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
ソースコード
// Bundled at 2024/10/14 20:05:11 +09:00
// Author: Haar
pub mod main {
use super::*;
use haar_lib::algebra::sum::*;
use haar_lib::ds::segtree::*;
use haar_lib::tree::{auxiliary_tree::*, hld::*, *};
#[allow(unused_imports)]
use haar_lib::{get, input, iter::join_str::*, utils::fastio::*};
#[allow(unused_imports)]
use std::cell::{Cell, RefCell};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet};
#[allow(unused_imports)]
use std::io::Write;
#[allow(unused_imports)]
use std::rc::Rc;
#[derive(Clone, Default)]
pub struct Problem {}
impl Problem {
pub fn main(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let mut io = FastIO::new();
let n = io.read_usize();
let mut builder = TreeBuilder::new(n);
for _ in 0..n - 1 {
let u = io.read_usize();
let v = io.read_usize();
let w = io.read_u64();
builder.extend(Some(TreeEdge::new(u, v, w, ())));
}
let tree = builder.build();
let monoid = Sum::<u64>::new();
let aux = AuxiliaryTree::new(&tree, 0);
let hld = HLD::new(tree.clone(), 0);
let mut seg = Segtree::new(n, monoid);
for e in tree.nodes_iter().flat_map(|a| a.neighbors()) {
if e.from() < e.to() {
seg.update(hld.get_edge_id(e.from(), e.to()).unwrap(), e.weight());
}
}
let q = io.read_usize();
for _ in 0..q {
let k = io.read_usize();
let x = get!(io, [usize; k]);
let x = aux.build(x, |a, b| hld.lca(a, b));
let k = x.len();
let mut ans = 0;
for i in 0..k {
for (l, r) in hld.path_query_edge(x[i], x[(i + 1) % k]) {
ans += seg.fold(l..r);
}
}
ans /= 2;
io.writeln(ans);
}
Ok(())
}
}
}
fn main() {
main::Problem::default().main().unwrap();
}
use crate as haar_lib;
pub mod algebra {
pub mod traits {
pub trait AlgeStruct {
type Output;
}
pub trait BinaryOp: AlgeStruct {
fn op(&self, _: Self::Output, _: Self::Output) -> Self::Output;
}
pub trait Identity: AlgeStruct {
fn id(&self) -> Self::Output;
}
pub trait Inverse: AlgeStruct {
fn inv(&self, _: Self::Output) -> Self::Output;
}
pub trait Commutative {}
pub trait Associative {}
pub trait Idempotence {}
pub trait Semigroup: BinaryOp + Associative {}
impl<T: BinaryOp + Associative> Semigroup for T {}
pub trait Monoid: Semigroup + Identity {}
impl<T: Semigroup + Identity> Monoid for T {}
pub trait AbelianMonoid: Monoid + Commutative {}
impl<T: Monoid + Commutative> AbelianMonoid for T {}
pub trait Group: Monoid + Inverse {}
impl<T: Monoid + Inverse> Group for T {}
pub trait AbelianGroup: Group + Commutative {}
impl<T: Group + Commutative> AbelianGroup for T {}
pub trait Times<T: Clone>: BinaryOp<Output = T> + Identity {
fn times(&self, mut a: Self::Output, mut n: u64) -> Self::Output {
let mut ret = self.id();
while n > 0 {
if n & 1 == 1 {
ret = self.op(ret, a.clone());
}
a = self.op(a.clone(), a);
n >>= 1;
}
ret
}
}
impl<T: Clone, A: BinaryOp<Output = T> + Identity> Times<T> for A {}
}
pub mod sum {
pub use crate::algebra::traits::*;
use crate::impl_algebra;
use std::marker::PhantomData;
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
pub struct Sum<T>(PhantomData<T>);
impl<T> Sum<T> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<T> AlgeStruct for Sum<T> {
type Output = T;
}
impl_algebra!(Sum<i8>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: i8| -a, commu: {}, assoc: {});
impl_algebra!(Sum<i16>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: i16| -a, commu: {}, assoc: {});
impl_algebra!(Sum<i32>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: i32| -a, commu: {}, assoc: {});
impl_algebra!(Sum<i64>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: i64| -a, commu: {}, assoc: {});
impl_algebra!(Sum<i128>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: i128| -a, commu: {}, assoc: {});
impl_algebra!(Sum<isize>, op: |_, a, b| a + b, id: |_| 0, inv: |_, a: isize| -a, commu: {}, assoc: {});
impl_algebra!(Sum<u8>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<u16>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<u32>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<u64>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<u128>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<usize>, op: |_, a, b| a + b, id: |_| 0, commu: {}, assoc: {});
impl_algebra!(Sum<f32>, op: |_, a, b| a + b, id: |_| 0.0, inv: |_, a: f32| -a, commu: {}, assoc: {});
impl_algebra!(Sum<f64>, op: |_, a, b| a + b, id: |_| 0.0, inv: |_, a: f64| -a, commu: {}, assoc: {});
}
}
pub mod ds {
pub mod segtree {
pub use crate::algebra::traits::Monoid;
use crate::utils::range::range_bounds_to_range;
use std::ops::{Index, RangeBounds};
#[derive(Clone)]
pub struct Segtree<M: Monoid> {
original_size: usize,
size: usize,
data: Vec<M::Output>,
monoid: M,
}
impl<T: Clone, M: Monoid<Output = T>> Segtree<M> {
pub fn new(n: usize, monoid: M) -> Self {
let size = n.next_power_of_two() * 2;
Segtree {
original_size: n,
size,
data: vec![monoid.id(); size],
monoid,
}
}
pub fn fold<R: RangeBounds<usize>>(&self, range: R) -> T {
let (l, r) = range_bounds_to_range(range, 0, self.size / 2);
let mut ret_l = self.monoid.id();
let mut ret_r = self.monoid.id();
let mut l = l + self.size / 2;
let mut r = r + self.size / 2;
while l < r {
if r & 1 == 1 {
r -= 1;
ret_r = self.monoid.op(self.data[r].clone(), ret_r);
}
if l & 1 == 1 {
ret_l = self.monoid.op(ret_l, self.data[l].clone());
l += 1;
}
r >>= 1;
l >>= 1;
}
self.monoid.op(ret_l, ret_r)
}
pub fn assign(&mut self, i: usize, value: T) {
let mut i = i + self.size / 2;
self.data[i] = value;
while i > 1 {
i >>= 1;
self.data[i] = self
.monoid
.op(self.data[i << 1].clone(), self.data[i << 1 | 1].clone());
}
}
pub fn update(&mut self, i: usize, value: T) {
self.assign(
i,
self.monoid.op(self.data[i + self.size / 2].clone(), value),
);
}
}
impl<T: Clone, M: Monoid<Output = T>> From<&Segtree<M>> for Vec<T> {
fn from(from: &Segtree<M>) -> Vec<T> {
from.data[from.size / 2..from.size / 2 + from.original_size].to_vec()
}
}
impl<M: Monoid> Index<usize> for Segtree<M> {
type Output = M::Output;
fn index(&self, i: usize) -> &Self::Output {
&self.data[self.size / 2 + i]
}
}
}
}
pub mod iter {
pub mod join_str {
pub trait JoinStr: Iterator {
fn join_str(self, s: &str) -> String
where
Self: Sized,
Self::Item: ToString,
{
self.map(|x| x.to_string()).collect::<Vec<_>>().join(s)
}
}
impl<I> JoinStr for I where I: Iterator + ?Sized {}
}
}
pub mod macros {
pub mod impl_algebra {
#[macro_export]
macro_rules! impl_algebra {
(@bound $t:ty, op: $f:expr; $($bound:tt)+) => {
impl <$($bound)+> BinaryOp for $t {
fn op(&self, a: Self::Output, b: Self::Output) -> Self::Output {
$f(&self, a, b)
}
}
};
(@nobound $t:ty, op: $f:expr) => {
impl BinaryOp for $t {
fn op(&self, a: Self::Output, b: Self::Output) -> Self::Output {
$f(&self, a, b)
}
}
};
(@bound $t:ty, id: $f:expr; $($bound:tt)+) => {
impl<$($bound)+> Identity for $t {
fn id(&self) -> Self::Output {
$f(&self)
}
}
};
(@nobound $t:ty, id: $f:expr) => {
impl Identity for $t {
fn id(&self) -> Self::Output {
$f(&self)
}
}
};
(@bound $t:ty, inv: $f:expr; $($bound:tt)+) => {
impl<$($bound)+> Inverse for $t {
fn inv(&self, a: Self::Output) -> Self::Output {
$f(self, a)
}
}
};
(@nobound $t:ty, inv: $f:expr) => {
impl Inverse for $t {
fn inv(&self, a: Self::Output) -> Self::Output {
$f(self, a)
}
}
};
(@bound $t:ty, commu: $f:expr; $($bound:tt)+) => {impl<$($bound)+> Commutative for $t {}};
(@nobound $t:ty, commu: $f:expr) => {impl Commutative for $t {}};
(@bound $t:ty, assoc: $f:expr; $($bound:tt)+) => {impl<$($bound)+> Associative for $t {}};
(@nobound $t:ty, assoc: $f:expr) => {impl Associative for $t {}};
(@bound $t:ty, idem: $f:expr; $($bound:tt)+) => {impl<$($bound)+> Idempotence for $t {}};
(@nobound $t:ty, idem: $f:expr) => {impl Idempotence for $t {}};
(const $a:ident : $b:ty; $t:ty, $($s:ident: $f:expr),+) => {
$(impl_algebra!(@bound $t, $s: $f; const $a: $b);)+
};
($a:ident; $t:ty, $($s:ident: $f:expr),+) => {
$(impl_algebra!(@bound $t, $s: $f; $a);)+
};
($t:ty, $($s:ident: $f:expr),+) => {
$(impl_algebra!(@nobound $t, $s: $f);)+
};
}
}
pub mod io {
#[macro_export]
macro_rules! get {
( $in:ident, [$a:tt $(as $to:ty)*; $num:expr] ) => {
{
let n = $num;
(0 .. n).map(|_| get!($in, $a $(as $to)*)).collect::<Vec<_>>()
}
};
( $in:ident, ($($type:tt $(as $to:ty)*),*) ) => {
($(get!($in, $type $(as $to)*)),*)
};
( $in:ident, i8 ) => { $in.read_i64() as i8 };
( $in:ident, i16 ) => { $in.read_i64() as i16 };
( $in:ident, i32 ) => { $in.read_i64() as i32 };
( $in:ident, i64 ) => { $in.read_i64() };
( $in:ident, isize ) => { $in.read_i64() as isize };
( $in:ident, u8 ) => { $in.read_u64() as u8 };
( $in:ident, u16 ) => { $in.read_u64() as u16 };
( $in:ident, u32 ) => { $in.read_u64() as u32 };
( $in:ident, u64 ) => { $in.read_u64() };
( $in:ident, usize ) => { $in.read_u64() as usize };
( $in:ident, [char] ) => { $in.read_chars() };
( $in:ident, $from:tt as $to:ty ) => { <$to>::from(get!($in, $from)) };
}
#[macro_export]
macro_rules! input {
( @inner $in:ident, mut $name:ident : $type:tt ) => {
let mut $name = get!($in, $type);
};
( @inner $in:ident, mut $name:ident : $type:tt as $to:ty ) => {
let mut $name = get!($in, $type as $to);
};
( @inner $in:ident, $name:ident : $type:tt ) => {
let $name = get!($in, $type);
};
( @inner $in:ident, $name:ident : $type:tt as $to:ty ) => {
let $name = get!($in, $type as $to);
};
( $in:ident >> $($($names:ident)* : $type:tt $(as $to:ty)*),* ) => {
$(input!(@inner $in, $($names)* : $type $(as $to)*);)*
}
}
}
}
pub mod tree {
pub mod auxiliary_tree {
use crate::tree::*;
pub struct AuxiliaryTree {
preorder: Vec<usize>,
}
impl AuxiliaryTree {
pub fn new<E: TreeEdgeTrait>(tree: &Tree<E>, root: usize) -> Self {
let n = tree.len();
let mut this = Self {
preorder: vec![0; n],
};
this.dfs(&tree, root, None, &mut 0);
this
}
fn dfs<E: TreeEdgeTrait>(
&mut self,
tree: &Tree<E>,
cur: usize,
par: Option<usize>,
i: &mut usize,
) {
self.preorder[cur] = *i;
*i += 1;
for e in tree.nodes[cur].neighbors() {
if Some(e.to()) != par {
self.dfs(tree, e.to(), Some(cur), i);
}
}
}
pub fn build<F>(&self, mut vs: Vec<usize>, f: F) -> Vec<usize>
where
F: Fn(usize, usize) -> usize,
{
vs.sort_by(|&a, &b| self.preorder[a].cmp(&self.preorder[b]));
let n = vs.len();
for i in 0..n - 1 {
let x = f(vs[i], vs[i + 1]);
vs.push(x);
}
vs.sort_by(|&a, &b| self.preorder[a].cmp(&self.preorder[b]));
vs.dedup();
vs
}
}
}
pub mod hld {
use crate::tree::*;
use std::cmp::max;
#[derive(Clone, Debug)]
pub struct HLD {
size: usize,
par: Vec<Option<usize>>,
head: Vec<usize>,
id: Vec<usize>,
rid: Vec<usize>,
next: Vec<Option<usize>>,
end: Vec<usize>,
}
impl HLD {
pub fn new<E: TreeEdgeTrait>(tree: Tree<E>, root: usize) -> Self {
let size = tree.len();
let mut ret = Self {
size,
par: vec![None; size],
head: vec![0; size],
id: vec![0; size],
rid: vec![0; size],
next: vec![None; size],
end: vec![0; size],
};
let mut tr = vec![vec![]; size];
for (i, nodes) in tree.nodes.iter().enumerate() {
for e in nodes.neighbors() {
tr[i].push(e.to());
}
}
ret.dfs_sub(&mut tr, root, None, &mut vec![1; size]);
ret.dfs_build(&tr, root, &mut 0);
ret
}
fn dfs_sub(
&mut self,
tree: &mut [Vec<usize>],
cur: usize,
par: Option<usize>,
sub: &mut Vec<usize>,
) {
self.par[cur] = par;
tree[cur].retain(|&x| Some(x) != par);
let mut t = 0;
let n = tree[cur].len();
for i in 0..n {
let to = tree[cur][i];
self.dfs_sub(tree, to, Some(cur), sub);
sub[cur] += sub[to];
if sub[to] > t {
t = sub[to];
self.next[cur] = Some(to);
tree[cur].swap(i, 0);
}
}
}
fn dfs_build(&mut self, tree: &[Vec<usize>], cur: usize, index: &mut usize) {
self.id[cur] = *index;
self.rid[*index] = cur;
*index += 1;
for (i, &to) in tree[cur].iter().enumerate() {
self.head[to] = if i == 0 { self.head[cur] } else { to };
self.dfs_build(tree, to, index);
}
self.end[cur] = *index;
}
pub fn path_query_vertex(&self, mut x: usize, mut y: usize) -> Vec<(usize, usize)> {
let mut ret = vec![];
loop {
if self.id[x] > self.id[y] {
std::mem::swap(&mut x, &mut y);
}
ret.push((max(self.id[self.head[y]], self.id[x]), self.id[y] + 1));
if self.head[x] == self.head[y] {
break;
}
y = self.par[self.head[y]].unwrap();
}
ret
}
pub fn path_query_edge(&self, mut x: usize, mut y: usize) -> Vec<(usize, usize)> {
let mut ret = vec![];
loop {
if self.id[x] > self.id[y] {
std::mem::swap(&mut x, &mut y);
}
if self.head[x] == self.head[y] {
if x != y {
ret.push((self.id[x] + 1, self.id[y] + 1));
}
break;
}
ret.push((self.id[self.head[y]], self.id[y] + 1));
y = self.par[self.head[y]].unwrap();
}
ret
}
pub fn subtree_query_vertex(&self, x: usize) -> (usize, usize) {
(self.id[x], self.end[x])
}
pub fn subtree_query_edge(&self, x: usize) -> (usize, usize) {
(self.id[x] + 1, self.end[x])
}
pub fn parent(&self, x: usize) -> Option<usize> {
self.par[x]
}
pub fn get_id(&self, x: usize) -> usize {
self.id[x]
}
pub fn get_edge_id(&self, u: usize, v: usize) -> Option<usize> {
if self.par[u] == Some(v) {
Some(self.id[u])
} else if self.par[v] == Some(u) {
Some(self.id[v])
} else {
None
}
}
pub fn lca(&self, mut u: usize, mut v: usize) -> usize {
loop {
if self.id[u] > self.id[v] {
std::mem::swap(&mut u, &mut v);
}
if self.head[u] == self.head[v] {
return u;
}
v = self.par[self.head[v]].unwrap();
}
}
}
}
pub trait TreeEdgeTrait {
type Weight;
fn from(&self) -> usize;
fn to(&self) -> usize;
fn weight(&self) -> Self::Weight;
fn rev(self) -> Self;
}
#[derive(Clone, Debug)]
pub struct TreeEdge<T, I> {
pub from: usize,
pub to: usize,
pub weight: T,
pub index: I,
}
impl<T, I> TreeEdge<T, I> {
pub fn new(from: usize, to: usize, weight: T, index: I) -> Self {
Self {
from,
to,
weight,
index,
}
}
}
impl<T: Clone, I> TreeEdgeTrait for TreeEdge<T, I> {
type Weight = T;
#[inline]
fn from(&self) -> usize {
self.from
}
#[inline]
fn to(&self) -> usize {
self.to
}
#[inline]
fn weight(&self) -> Self::Weight {
self.weight.clone()
}
fn rev(mut self) -> Self {
std::mem::swap(&mut self.from, &mut self.to);
self
}
}
#[derive(Clone, Debug, Default)]
pub struct TreeNode<E> {
pub parent: Option<E>,
pub children: Vec<E>,
}
impl<E: TreeEdgeTrait> TreeNode<E> {
pub fn neighbors(&self) -> impl DoubleEndedIterator<Item = &E> {
self.children.iter().chain(self.parent.iter())
}
pub fn neighbors_size(&self) -> usize {
self.children.len() + self.parent.as_ref().map_or(0, |_| 1)
}
}
pub struct TreeBuilder<E> {
nodes: Vec<TreeNode<E>>,
}
impl<E: TreeEdgeTrait + Clone> TreeBuilder<E> {
pub fn new(size: usize) -> Self {
Self {
nodes: vec![
TreeNode {
parent: None,
children: vec![],
};
size
],
}
}
pub fn extend(&mut self, edges: impl IntoIterator<Item = E>) {
for e in edges {
self.nodes[e.from()].children.push(e.clone());
self.nodes[e.to()].children.push(e.rev());
}
}
pub fn build(self) -> Tree<E> {
Tree {
nodes: self.nodes,
root: None,
}
}
}
pub struct RootedTreeBuilder<E> {
nodes: Vec<TreeNode<E>>,
root: usize,
}
impl<E: TreeEdgeTrait + Clone> RootedTreeBuilder<E> {
pub fn new(size: usize, root: usize) -> Self {
Self {
nodes: vec![
TreeNode {
parent: None,
children: vec![],
};
size
],
root,
}
}
pub fn extend(&mut self, edges: impl IntoIterator<Item = E>) {
for e in edges {
assert!(self.nodes[e.to()].parent.is_none());
self.nodes[e.from()].children.push(e.clone());
self.nodes[e.to()].parent.replace(e.rev());
}
}
pub fn build(self) -> Tree<E> {
Tree {
nodes: self.nodes,
root: Some(self.root),
}
}
}
#[derive(Clone, Debug)]
pub struct Tree<E> {
nodes: Vec<TreeNode<E>>,
root: Option<usize>,
}
impl<E> Tree<E> {
pub fn nodes_iter(&self) -> impl Iterator<Item = &TreeNode<E>> {
self.nodes.iter()
}
pub fn nodes(&self, i: usize) -> &TreeNode<E> {
&self.nodes[i]
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn root(&self) -> Option<usize> {
self.root
}
}
}
pub mod utils {
pub mod fastio {
use std::fmt::Display;
use std::io::{Read, Write};
pub struct FastIO {
in_bytes: Vec<u8>,
in_cur: usize,
out_buf: std::io::BufWriter<std::io::Stdout>,
}
impl FastIO {
pub fn new() -> Self {
let mut s = vec![];
std::io::stdin().read_to_end(&mut s).unwrap();
let cout = std::io::stdout();
Self {
in_bytes: s,
in_cur: 0,
out_buf: std::io::BufWriter::new(cout),
}
}
#[inline]
pub fn getc(&mut self) -> Option<u8> {
if self.in_cur < self.in_bytes.len() {
self.in_cur += 1;
Some(self.in_bytes[self.in_cur])
} else {
None
}
}
#[inline]
pub fn peek(&self) -> Option<u8> {
if self.in_cur < self.in_bytes.len() {
Some(self.in_bytes[self.in_cur])
} else {
None
}
}
#[inline]
pub fn skip(&mut self) {
while self.peek().map_or(false, |c| c.is_ascii_whitespace()) {
self.in_cur += 1;
}
}
pub fn read_u64(&mut self) -> u64 {
self.skip();
let mut ret: u64 = 0;
while self.peek().map_or(false, |c| c.is_ascii_digit()) {
ret = ret * 10 + (self.in_bytes[self.in_cur] - b'0') as u64;
self.in_cur += 1;
}
ret
}
pub fn read_u32(&mut self) -> u32 {
self.read_u64() as u32
}
pub fn read_usize(&mut self) -> usize {
self.read_u64() as usize
}
pub fn read_i64(&mut self) -> i64 {
self.skip();
let mut ret: i64 = 0;
let minus = if self.peek() == Some(b'-') {
self.in_cur += 1;
true
} else {
false
};
while self.peek().map_or(false, |c| c.is_ascii_digit()) {
ret = ret * 10 + (self.in_bytes[self.in_cur] - b'0') as i64;
self.in_cur += 1;
}
if minus {
ret = -ret;
}
ret
}
pub fn read_i32(&mut self) -> i32 {
self.read_i64() as i32
}
pub fn read_isize(&mut self) -> isize {
self.read_i64() as isize
}
pub fn read_f64(&mut self) -> f64 {
self.read_chars()
.into_iter()
.collect::<String>()
.parse()
.unwrap()
}
pub fn read_chars(&mut self) -> Vec<char> {
self.skip();
let mut ret = vec![];
while self.peek().map_or(false, |c| c.is_ascii_graphic()) {
ret.push(self.in_bytes[self.in_cur] as char);
self.in_cur += 1;
}
ret
}
pub fn write<T: Display>(&mut self, s: T) {
self.out_buf.write_all(format!("{}", s).as_bytes()).unwrap();
}
pub fn writeln<T: Display>(&mut self, s: T) {
self.write(s);
self.out_buf.write_all(&[b'\n']).unwrap();
}
}
impl Drop for FastIO {
fn drop(&mut self) {
self.out_buf.flush().unwrap();
}
}
}
pub mod range {
use std::ops::RangeBounds;
pub fn range_bounds_to_range<R: RangeBounds<usize>>(
r: R,
start: usize,
end: usize,
) -> (usize, usize) {
use std::ops::Bound::*;
let l = match r.start_bound() {
Included(&l) => l,
Excluded(&l) => l + 1,
Unbounded => start,
}
.max(start);
let r = match r.end_bound() {
Included(&r) => r + 1,
Excluded(&r) => r,
Unbounded => end,
}
.min(end);
(l, r)
}
}
}