テンプレート (IO・スレッド生成)
概要
一部のスタックが浅いオンラインジャッジ対策として,スタックサイズを指定してスレッドを生成する. IO はパフォーマスと使いやすさ再優先のため,unsafe も unwrap もカジュアルに使っている. ASCII 文字以外の入力は受け付けない.
使い方
fn solve() {
while has_next() {
let n: i32 = get();
let (n, m): (i32, i32) = get();
p!(n, m);
pf!(n, m); // 出力後にバッファをフラッシュ
d!(n, m);
}
}
実装
use std::io::*;
use std::str::FromStr;
#[allow(unused_imports)]
use std::collections::*;
#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_macros)]
macro_rules! dump (
($($arg:tt)*) => { {
if cfg!(local) {
// TODO: add line number
let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
r.expect("failed printing to stderr");
}
} }
);
#[allow(unused_macros)]
macro_rules! exit {
() => {{
exit!(0)
}};
($code:expr) => {{
if cfg!(local) {
writeln!(std::io::stderr(), "===== Terminated =====")
.expect("failed printing to stderr");
}
std::process::exit($code);
}}
}
struct Scanner<I: Iterator<Item = char>> {
iter: std::iter::Peekable<I>,
}
#[allow(dead_code)]
impl<I: Iterator<Item = char>> Scanner<I> {
pub fn new(iter: I) -> Scanner<I> {
Scanner {
iter: iter.peekable(),
}
}
pub fn safe_get_token(&mut self) -> Option<String> {
let token = self.iter
.by_ref()
.skip_while(|c| c.is_ascii_whitespace())
.take_while(|c| !c.is_ascii_whitespace())
.collect::<String>();
if token.is_empty() {
None
} else {
Some(token)
}
}
pub fn token(&mut self) -> String {
self.safe_get_token().unwrap_or_else(|| exit!())
}
pub fn get<T: FromStr>(&mut self) -> T {
self.token().parse::<T>().unwrap_or_else(|_| exit!())
}
pub fn vec<T: FromStr>(&mut self, len: usize) -> Vec<T> {
(0..len).map(|_| self.get()).collect()
}
pub fn mat<T: FromStr>(&mut self, row: usize, col: usize) -> Vec<Vec<T>> {
(0..row).map(|_| self.vec(col)).collect()
}
pub fn char(&mut self) -> char {
self.iter.next().unwrap_or_else(|| exit!())
}
pub fn graphic_char(&mut self) -> char {
self.iter
.by_ref()
.skip_while(|c| !c.is_ascii_graphic())
.next()
.unwrap_or_else(|| exit!())
}
pub fn line(&mut self) -> String {
if self.peek().is_some() {
self.iter
.by_ref()
.take_while(|&c| !(c == '\n' || c == '\r'))
.collect::<String>()
} else {
exit!();
}
}
pub fn peek(&mut self) -> Option<&char> {
self.iter.peek()
}
}
trait Joinable {
fn join(self, sep: &str) -> String;
}
impl<U: ToString, T: Iterator<Item = U>> Joinable for T {
fn join(self, sep: &str) -> String {
self.map(|x| x.to_string()).collect::<Vec<_>>().join(sep)
}
}
trait CheckBetween {
fn is_between(&self, low: Self, high: Self) -> bool;
}
impl<T: PartialOrd + Copy> CheckBetween for T {
fn is_between(&self, low: T, high: T) -> bool {
low <= *self && *self <= high
}
}
fn main() {
std::thread::Builder::new()
.stack_size(104_857_600)
.spawn(solve)
.unwrap()
.join()
.unwrap();
}
fn solve() {
let cin = stdin();
let cin = cin.lock();
let mut sc = Scanner::new(cin.bytes().map(|c| c.unwrap() as char));
let _n: u32 = sc.get();
}