Fast IO

Code

#![no_main]

#[allow(unused)]
use std::{cmp::*, collections::*, iter, mem::*, num::*, ops::*};

fn solve<'t, It: Iterator<Item = &'t str>>(sc: &mut fastio::Tokenizer<It>) {}

#[allow(unused)]
mod fastio {
	use super::ioutil::*;

	pub struct Tokenizer<It> {
		it: It,
	}

	impl<'i, 's: 'i, It> Tokenizer<It> {
		pub fn new(text: &'s str, split: impl FnOnce(&'i str) -> It) -> Self {
			Self { it: split(text) }
		}
	}

	impl<'t, It: Iterator<Item = &'t str>> Tokenizer<It> {
		pub fn next_ok<T: IterParse<'t>>(&mut self) -> PRes<'t, T> {
			T::parse_from_iter(&mut self.it)
		}

		pub fn next<T: IterParse<'t>>(&mut self) -> T {
			self.next_ok().unwrap()
		}

		pub fn next_map<T: IterParse<'t>, U, const N: usize>(&mut self, f: impl FnMut(T) -> U) -> [U; N] {
			let x: [T; N] = self.next();
			x.map(f)
		}

		pub fn next_it<T: IterParse<'t>>(&mut self) -> impl Iterator<Item = T> + '_ {
			std::iter::repeat_with(move || self.next_ok().ok()).map_while(|x| x)
		}

		pub fn next_collect<T: IterParse<'t>, V: FromIterator<T>>(&mut self, size: usize) -> V {
			self.next_it().take(size).collect()
		}
	}
}

mod ioutil {
	use std::{fmt::*, num::*};

	pub enum InputError<'t> {
		InputExhaust,
		ParseError(&'t str),
	}
	use InputError::*;

	pub type PRes<'t, T> = std::result::Result<T, InputError<'t>>;

	impl<'t> Debug for InputError<'t> {
		fn fmt(&self, f: &mut Formatter<'_>) -> Result {
			match self {
				InputExhaust => f.debug_struct("InputExhaust").finish(),
				ParseError(s) => f.debug_struct("ParseError").field("str", s).finish(),
			}
		}
	}

	pub trait Atom<'t>: Sized {
		fn parse(text: &'t str) -> PRes<'t, Self>;
	}

	impl<'t> Atom<'t> for &'t str {
		fn parse(text: &'t str) -> PRes<'t, Self> {
			Ok(text)
		}
	}

	impl<'t> Atom<'t> for &'t [u8] {
		fn parse(text: &'t str) -> PRes<'t, Self> {
			Ok(text.as_bytes())
		}
	}

	macro_rules! impl_atom {
        ($($t:ty) *) => { $(impl Atom<'_> for $t { fn parse(text: &str) -> PRes<Self> { text.parse().map_err(|_| ParseError(text)) } })* };
    }
	impl_atom!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64 bool char String NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize);

	pub trait IterParse<'t>: Sized {
		fn parse_from_iter<'s, It: Iterator<Item = &'t str>>(it: &'s mut It) -> PRes<'t, Self>
		where
			't: 's;
	}

	impl<'t, A: Atom<'t>> IterParse<'t> for A {
		fn parse_from_iter<'s, It: Iterator<Item = &'t str>>(it: &'s mut It) -> PRes<'t, Self>
		where
			't: 's,
		{
			it.next().map_or(Err(InputExhaust), <Self as Atom>::parse)
		}
	}

	impl<'t, A: IterParse<'t>, const N: usize> IterParse<'t> for [A; N] {
		fn parse_from_iter<'s, It: Iterator<Item = &'t str>>(it: &'s mut It) -> PRes<'t, Self>
		where
			't: 's,
		{
			use std::mem::*;
			let mut x: [MaybeUninit<A>; N] = unsafe { MaybeUninit::uninit().assume_init() };
			for p in x.iter_mut() {
				*p = MaybeUninit::new(A::parse_from_iter(it)?);
			}
			Ok(unsafe { transmute_copy(&x) })
		}
	}

	macro_rules! impl_tuple {
        ($u:ident) => {};
        ($u:ident $($t:ident)+) => { impl<'t, $u: IterParse<'t>, $($t: IterParse<'t>),+> IterParse<'t> for ($u, $($t),+) { fn parse_from_iter<'s, It: Iterator<Item = &'t str>>(_it: &'s mut It) -> PRes<'t, Self> where 't: 's { Ok(($u::parse_from_iter(_it)?, $($t::parse_from_iter(_it)?),+)) } } impl_tuple!($($t) +); };
    }

	impl_tuple!(Q W E R T Y U I O P A S D F G H J K L Z X C V B N M);
}

#[link(name = "c")]
extern "C" {
	fn mmap(addr: usize, len: usize, p: i32, f: i32, fd: i32, o: i64) -> *mut u8;
	fn fstat(fd: i32, stat: *mut usize) -> i32;
}

fn get_input() -> &'static str {
	let mut stat = [0; 20];
	unsafe { fstat(0, stat.as_mut_ptr()) };
	let buffer = unsafe { mmap(0, stat[6], 1, 2, 0, 0) };
	unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(buffer, stat[6])) }
}

#[no_mangle]
unsafe fn main() -> i32 {
	use std::io::*;
	let mut sc = fastio::Tokenizer::new(get_input(), |s| s.split_ascii_whitespace());
	let stdout = stdout();
	WRITER = Some(BufWriter::new(stdout.lock()));
	solve(&mut sc);
	WRITER.as_mut().unwrap_unchecked().flush().ok();
	0
}

use std::io::{BufWriter, StdoutLock};
static mut WRITER: Option<BufWriter<StdoutLock>> = None;
#[macro_export]
macro_rules! print {
    ($($t:tt)*) => {{ use std::io::*; write!(unsafe{ WRITER.as_mut().unwrap_unchecked() }, $($t)*).unwrap(); }};
}
#[macro_export]
macro_rules! println {
    ($($t:tt)*) => {{ use std::io::*; writeln!(unsafe{ WRITER.as_mut().unwrap_unchecked() }, $($t)*).unwrap(); }};
}

Last modified on 231008.