Submission #37589533


Source Code Expand

// -*- coding:utf-8-unix -*-
// rustup doc --std --toolchain 1.42.0

#![allow(unused_imports)]
#![allow(unused_macros)]
/*
use bitset_fixed::BitSet;
use fixedbitset::FixedBitSet;
use itertools::*;
use num::integer::*;
use petgraph::algo::*;
use petgraph::graph::{DiGraph, Graph, NodeIndex, UnGraph};
use petgraph::unionfind::UnionFind;
use petgraph::visit::{
    Bfs, Dfs, EdgeRef, IntoEdges, NodeCount, NodeIndexable, VisitMap, Visitable,
};
//use proconio::{input, marker::{Bytes, Chars, Isize1, Usize1}, source::{auto::AutoSource, line::LineSource, once::OnceSource}};
use rand::{
    distributions::WeightedIndex,
    prelude::{thread_rng, Distribution},
    seq::SliceRandom,
    Rng,
};
use regex::Regex;
use std::collections::*;
use std::io::{stderr, stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::ops::*;
use superslice::Ext;
*/

// 1024bit BitSet
const FBITSET_LEN: usize = 1024 / 64;
#[derive(Debug, Clone)]
pub struct FBitSet([u64; FBITSET_LEN]);
impl FBitSet {
    pub fn new() -> Self {
        Self([0; FBITSET_LEN])
    }
    pub fn clone_from(&mut self, f: &Self) {
        unsafe { std::ptr::copy(f.0.as_ptr(), self.0.as_mut_ptr(), FBITSET_LEN) }
    }
    pub fn is_zero(&self) -> bool {
        for &e in &self.0 {
            if e != 0 {
                return false;
            }
        }
        true
    }
    pub fn get(&self, i: usize) -> u64 {
        unsafe { ((*self.0.get_unchecked(i / 64)) >> (i % 64)) & 1 }
    }
    pub fn set(&mut self, i: usize, f: bool) {
        if f {
            unsafe { (*self.0.get_unchecked_mut(i / 64)) |= 1 << (i % 64) };
        } else {
            unsafe { (*self.0.get_unchecked_mut(i / 64)) &= !(1 << (i % 64)) };
        }
    }
    pub fn buffer_mut(&mut self) -> &mut [u64] {
        &mut self.0
    }
    pub fn not_assign(&mut self) {
        for s in self.0.iter_mut() {
            *s = !(*s);
        }
    }
    pub fn bitand_assign(&mut self, rhs: &Self) {
        for (s, r) in self.0.iter_mut().zip(rhs.0.iter()) {
            *s &= *r;
        }
    }
    pub fn bitxor_assign(&mut self, rhs: &Self) {
        for (s, r) in self.0.iter_mut().zip(rhs.0.iter()) {
            *s ^= *r;
        }
    }
    pub fn shl1_assign(&mut self) {
        for i in (1..FBITSET_LEN).rev() {
            self.0[i] <<= 1;
            self.0[i] |= self.0[i - 1] >> 63;
        }
        self.0[0] <<= 1;
    }
    pub fn shr1_assign(&mut self) {
        for i in 0..(FBITSET_LEN - 1) {
            self.0[i] >>= 1;
            self.0[i] |= self.0[i + 1].wrapping_shl(63);
        }
        self.0[FBITSET_LEN - 1] >>= 1;
    }
}

pub fn solve() {
    let tins = std::time::Instant::now();
    let mut durs = Vec::with_capacity(16);
    use fastproconio::*;
    let stdin = std::io::stdin();
    let mut source = fastproconio::ProconIBufIter::new(stdin.lock());
    macro_rules! finput { ($($r:tt)*) => { finput_inner!{source, $($r)*} }; }
    //let mut out = std::io::BufWriter::new(out.lock());
    //let err = std::io::stderr();
    //let mut err = std::io::BufWriter::new(err.lock());
    finput! {
        h: usize, w: usize,
    }
    debug_assert!(w < FBITSET_LEN * 64);
    let w1 = w - 1;
    let w2 = w - 2;
    let mut work = FBitSet::new();
    let mut curr_p = FBitSet::new();
    let mut curr_n = FBitSet::new();
    let mut curr_a = FBitSet::new();
    let mut prev_p = FBitSet::new();
    let mut prev_n = FBitSet::new();
    let mut prev_a = FBitSet::new();
    for j in &mut curr_p.buffer_mut()[0..(w / 64)] {
        let mut v = 0u64;
        let mut x = 1u64;
        while x != 0 {
            finput! { a: u8 }
            v |= if a != 0 { x } else { 0 };
            x = x.wrapping_shl(1);
        }
        *j = v;
    }
    //if w % 64 != 0
    {
        let mut v = 0u64;
        let mut x = 1u64;
        for _ in 0..(w % 64) {
            finput! { a: u8 }
            v |= if a != 0 { x } else { 0 };
            x = x.wrapping_shl(1);
        }
        curr_p.buffer_mut()[w / 64] = v;
    }
    curr_n.clone_from(&curr_p);
    curr_n.not_assign();
    curr_a.clone_from(&curr_p);
    curr_a.shl1_assign();
    curr_a.bitxor_assign(&curr_p);
    work.clone_from(&curr_a);
    work.shr1_assign();
    curr_a.bitand_assign(&work);
    curr_a.set(0, curr_p.get(0) != curr_p.get(1));
    curr_a.set(w1, curr_p.get(w2) != curr_p.get(w1));
    let mut dp: [Option<u32>; 4] = [Some(0), Some(1), Some(0), Some(1)];
    let mut alones: [FBitSet; 8] = [
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
        curr_a.clone(),
    ];
    for _i in 1..h {
        std::mem::swap(&mut prev_p, &mut curr_p);
        std::mem::swap(&mut prev_n, &mut curr_n);
        std::mem::swap(&mut prev_a, &mut curr_a);
        for j in &mut curr_p.buffer_mut()[0..(w / 64)] {
            let mut v = 0u64;
            let mut x = 1u64;
            while x != 0 {
                finput! { a: u8 }
                v |= if a != 0 { x } else { 0 };
                x = x.wrapping_shl(1);
            }
            *j = v;
        }
        //if w % 64 != 0
        {
            let mut v = 0u64;
            let mut x = 1u64;
            for _ in 0..(w % 64) {
                finput! { a: u8 }
                v |= if a != 0 { x } else { 0 };
                x = x.wrapping_shl(1);
            }
            curr_p.buffer_mut()[w / 64] = v;
        }
        curr_n.clone_from(&curr_p);
        curr_n.not_assign();
        curr_a.clone_from(&curr_p);
        curr_a.shl1_assign();
        curr_a.bitxor_assign(&curr_p);
        work.clone_from(&curr_a);
        work.shr1_assign();
        curr_a.bitand_assign(&work);
        curr_a.set(0, curr_p.get(0) != curr_p.get(1));
        curr_a.set(w1, curr_p.get(w2) != curr_p.get(w1));
        alones.swap(0, 4);
        alones.swap(1, 5);
        alones.swap(2, 6);
        alones.swap(3, 7);
        alones[0].clone_from(&prev_p);
        alones[1].clone_from(&prev_p);
        alones[2].clone_from(&prev_n);
        alones[3].clone_from(&prev_n);
        alones[0].bitxor_assign(&curr_p);
        alones[1].bitxor_assign(&curr_n);
        alones[2].bitxor_assign(&curr_p);
        alones[3].bitxor_assign(&curr_n);
        let mut ndp: [Option<u32>; 4] = [None, None, None, None];
        macro_rules! jexec {
            ($j:literal) => {{
                let j = $j;
                let mut dp_e = None;
                if let Some(pcount) = dp[j >> 1] {
                    work.clone_from(&alones[j]);
                    work.bitand_assign(&alones[4 + (j >> 1)]);
                    if work.is_zero() {
                        let curr_count = pcount + ((j as u32) & 1);
                        dp_e = Some(curr_count);
                    }
                }
                if let Some(pcount) = dp[2 + (j >> 1)] {
                    work.clone_from(&alones[j]);
                    work.bitand_assign(&alones[6 + (j >> 1)]);
                    if work.is_zero() {
                        let curr_count = pcount + ((j as u32) & 1);
                        if let Some(c) = dp_e {
                            if c > curr_count {
                                dp_e = Some(curr_count);
                            }
                        } else {
                            dp_e = Some(curr_count);
                        }
                    }
                }
                ndp[j] = dp_e;
            }};
        }
        jexec!(0);
        jexec!(1);
        jexec!(2);
        jexec!(3);
        dp = ndp;
        alones[0].bitand_assign(&curr_a);
        alones[1].bitand_assign(&curr_a);
        alones[2].bitand_assign(&curr_a);
        alones[3].bitand_assign(&curr_a);
    }
    for i in 0..4 {
        if !alones[i].is_zero() {
            dp[i] = None;
        }
    }
    let result = dp.iter().fold(None, |p, &c| {
        if p.is_none() {
            c
        } else if c.is_none() {
            p
        } else {
            Some(p.unwrap().min(c.unwrap()))
        }
    });
    let mut out = std::io::stdout();
    let mut obuf = fastproconio::ProconWriteBuffer::with_capacity(1 << 8);
    if let Some(count) = result {
        obuf.uint(count);
    } else {
        obuf.str("-1");
    }
    obuf.lf();
    obuf.write_all(&mut out);
    let _ = std::io::Write::flush(&mut out);
    durs.push((tins.elapsed(), "output"));
    for (dur, s) in &durs {
        eprintln!("{:.6} {}", dur.as_secs_f64(), s);
    }
    //let _ = writeln!(&mut err, "{}", count);
    //let _ = std::io::Write::flush(&mut err);
}

pub fn main() {
    const USE_THREAD: bool = false;
    if USE_THREAD {
        // In order to avoid potential stack overflow, spawn a new thread.
        let stack_size = 134_217_728; // 128 MB
        let thd = std::thread::Builder::new().stack_size(stack_size);
        thd.spawn(|| solve()).unwrap().join().unwrap();
    } else {
        solve()
    }
}

/// chmax, chmin sugar syntax
trait Change {
    fn chmax(&mut self, x: Self);
    fn chmin(&mut self, x: Self);
}
impl<T: PartialOrd> Change for T {
    fn chmax(&mut self, x: T) {
        if *self < x {
            *self = x;
        }
    }
    fn chmin(&mut self, x: T) {
        if *self > x {
            *self = x;
        }
    }
}
pub mod fastproconio {
    /// input macros based on tanakh's input macro / proconio-rs.
    /// tanakh's input macro: <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
    /// proconio-rs: <https://docs.rs/proconio/0.3.8/proconio/>
    /// this macro recieve `Iterator<Item = u8>` input source, except for Bytes/Chars/String read
    /// ProconIBufIter receive `std::io::BufRead` trait. (`std::io::StdinLock`, `std::io::BufReader`, `&[u8]`, etc.)
    #[macro_export]
    macro_rules! finput_inner {
        ($iter:expr) => {};
        ($iter:expr, ) => {};
        ($iter:expr, mut $var:ident : $t:tt $($r:tt)*) => {
            let mut $var = fread_value!($iter, $t);
            finput_inner!{$iter $($r)*}
        };
        ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
            let $var = fread_value!($iter, $t);
            finput_inner!{$iter $($r)*}
        };
    }
    #[macro_export]
    macro_rules! fread_value {
        ($iter:expr, ( $($t:tt),* )) => { ( $(fread_value!($iter, $t)),* ) };
        ($iter:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| fread_value!($iter, $t)).collect::<Vec<_>>() };
        ($iter:expr, u128) => { $iter.parse_uint::<u128>() };
        ($iter:expr, usize) => { $iter.parse_uint::<usize>() };
        ($iter:expr, usize1) => { $iter.parse_uint::<usize>() - 1 };
        ($iter:expr, u64) => { $iter.parse_uint::<u64>() };
        ($iter:expr, u64_1) => { $iter.parse_uint::<u64>() - 1 };
        ($iter:expr, u32) => { $iter.parse_uint::<u32>() };
        ($iter:expr, u32_1) => { $iter.parse_uint::<u32>() - 1 };
        ($iter:expr, u16) => { $iter.parse_uint::<u16>() };
        ($iter:expr, u8) => { $iter.parse_uint::<u8>() };
        ($iter:expr, i128) => { $iter.parse_iint::<i128>() };
        ($iter:expr, isize) => { $iter.parse_iint::<isize>() };
        ($iter:expr, i64) => { $iter.parse_iint::<i64>() };
        ($iter:expr, i32) => { $iter.parse_iint::<i32>() };
        ($iter:expr, i16) => { $iter.parse_iint::<i16>() };
        ($iter:expr, i8) => { $iter.parse_iint::<i16>() as i8 };
        ($iter:expr, byte) => { $iter.get_ascii_byte().unwrap() };
        ($iter:expr, Bytes) => {{ let mut v = vec![];$iter.get_ascii_bytes(&mut v);v }};
        ($iter:expr, Chars) => {{ let mut v = vec![];$iter.get_ascii_chars(&mut v);v }};
        ($iter:expr, String) => {{ let mut v = vec![];$iter.get_ascii_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, LineBytes) => {{ let mut v = vec![];$iter.get_ascii_line_bytes(&mut v).and(Some(v)).unwrap() }};
        ($iter:expr, LineBytesTrim) => {{ let mut v = vec![];$iter.get_ascii_line_bytes_trim(&mut v);v }};
        ($iter:expr, LineString) => {{ let mut v = vec![];$iter.get_ascii_line_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, LineStringTrim) => {{ let mut v = vec![];$iter.get_ascii_line_bytes_trim(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8Bytes) => {{ let mut v = vec![];$iter.get_utf8_bytes(&mut v);v }};
        ($iter:expr, Utf8String) => {{ let mut v = vec![];$iter.get_utf8_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8LineBytes) => {{ let mut v = vec![];$iter.get_utf8_line_bytes(&mut v);v }};
        ($iter:expr, Utf8LineBytesTrim) => {{ let mut v = vec![];$iter.get_utf8_line_bytes_trim(&mut v);v }};
        ($iter:expr, Utf8LineString) => {{ let mut v = vec![];$iter.get_utf8_line_bytes(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, Utf8LineStringTrim) => {{ let mut v = vec![];$iter.get_utf8_line_bytes_trim(&mut v);unsafe { std::string::String::from_utf8_unchecked(v) }}};
        ($iter:expr, $t:ty) => {{ let mut v = vec![];unsafe { std::string::String::from_utf8_unchecked($iter.get_utf8_bytes(&mut v).and(Some(v)).unwrap()) }.parse::<$t>().expect("Parse error") }};
    }

    /// Interaction with `std::io::BufRead` Trait, Implementation of `Iterator<Item = u8>`
    pub struct ProconIBufIter<R: std::io::BufRead> {
        inner: R,
        raw: *const u8,
        len: usize,
        ptr: *const u8,
        end: *const u8,
    }
    unsafe fn ptr_offset_u8(dist: *const u8, origin: *const u8) -> usize {
        // Rust 1.47.0 or later, `dist.offset_from(origin) as usize`
        // <https://doc.rust-lang.org/std/primitive.pointer.html#method.offset_from>
        dist as usize - origin as usize
    }
    impl<R: std::io::BufRead> ProconIBufIter<R> {
        /// consume raw buffer
        #[allow(unused)]
        fn consume(&mut self, amt: usize) {
            let remain = unsafe { ptr_offset_u8(self.end, self.ptr) };
            assert!(remain >= amt);
            unsafe {
                self.ptr = self.ptr.add(amt);
            }
        }
        /// read when buffer is empty
        unsafe fn inner_read(&mut self) -> bool {
            assert!(self.is_empty());
            self.inner.consume(self.len);
            let buffer = self.inner.fill_buf().unwrap();
            let raw = buffer.as_ptr();
            let len = buffer.len();
            self.raw = raw;
            self.len = len;
            self.ptr = raw;
            self.end = raw.add(len);
            self.len > 0
        }
        /// check end of buffer
        fn is_empty(&self) -> bool {
            self.ptr == self.end
        }
        /// Interaction with `std::io::BufRead` Trait, Implementation of `Iterator<Item = u8>`
        pub fn new(inner: R) -> Self {
            let mut bufiter = Self {
                inner,
                raw: std::ptr::null(),
                len: 0,
                ptr: std::ptr::null(),
                end: std::ptr::null(),
            };
            unsafe { bufiter.inner_read() };
            bufiter
        }
        /// next(), but return empty value
        #[allow(unused)]
        fn next_unread(&mut self) -> Option<()> {
            if self.is_empty() && unsafe { !self.inner_read() } {
                return None;
            }
            unsafe {
                self.ptr = self.ptr.add(1);
            }
            return Some(());
        }
        /// get now pointer & increment pointer
        unsafe fn next_unchecked(&mut self) -> u8 {
            let p = self.ptr;
            self.ptr = p.add(1);
            *p
        }
        /// peek
        #[allow(unused)]
        fn peek(&mut self) -> Option<&u8> {
            if !self.is_empty() || unsafe { self.inner_read() } {
                unsafe { Some(&*self.ptr) }
            } else {
                None
            }
        }
        /// raw buffer
        #[allow(unused)]
        fn raw_buf(&mut self) -> &[u8] {
            if self.is_empty() {
                unsafe {
                    self.inner_read();
                }
            }
            unsafe { std::slice::from_raw_parts(self.ptr, ptr_offset_u8(self.end, self.ptr)) }
        }
        /// skip unmatch bytes
        fn skipuntil_bytes_fn<F: FnMut(u8) -> bool>(&mut self, f: &mut F) -> bool {
            loop {
                let mut ptr = self.ptr;
                while ptr != self.end {
                    if f(unsafe { *ptr }) {
                        self.ptr = ptr;
                        return true;
                    }
                    unsafe {
                        ptr = ptr.add(1);
                    }
                }
                self.ptr = ptr;
                if unsafe { !self.inner_read() } {
                    return false;
                }
            }
        }
    }
    impl<R: std::io::BufRead> Iterator for ProconIBufIter<R> {
        type Item = u8;
        /// fetch next byte
        fn next(&mut self) -> Option<Self::Item> {
            if !self.is_empty() || unsafe { self.inner_read() } {
                unsafe { Some(self.next_unchecked()) }
            } else {
                None
            }
        }
        /// remain size hint
        fn size_hint(&self) -> (usize, Option<usize>) {
            (unsafe { ptr_offset_u8(self.end, self.ptr) }, None)
        }
    }
    impl<R: std::io::BufRead> Drop for ProconIBufIter<R> {
        /// Saving the pointer on interruption
        fn drop(&mut self) {
            self.inner
                .consume(unsafe { ptr_offset_u8(self.ptr, self.raw) });
        }
    }
    /// speed frenzy input parser for program compete (fail parse may cause undefined behavior)
    pub trait ProconParse {
        /// parse unsigned integer
        fn parse_uint<
            U: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = U>
                + std::ops::Add<Output = U>
                + std::ops::Sub<Output = U>
                + std::ops::Mul<Output = U>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> U;
        /// parse signed integer
        fn parse_iint<
            I: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = I>
                + std::ops::Add<Output = I>
                + std::ops::Sub<Output = I>
                + std::ops::Mul<Output = I>
                + std::convert::From<u8>
                + std::ops::Neg<Output = I>,
        >(
            &mut self,
        ) -> I;
        /// get char (printable ascii char)
        fn parse_byte(&mut self) -> Option<u8>;
        /// get chars (printable ascii word)
        fn parse_bytes(&mut self) -> Vec<u8>;
        /// get line chars (sp+printable ascii)
        fn parse_line_bytes(&mut self) -> Vec<u8>;
        /// get line chars (trimed sp+printable ascii)
        fn parse_line_bytes_trim(&mut self) -> Vec<u8>;
    }
    /// speed frenzy input byte reader for program compete
    pub trait ProconBytes {
        /// get bytes
        fn get_bytes_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<u8>, f: &mut F);
        /// get chars
        fn get_ascii_chars_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<char>, f: &mut F);
        /// get byte (printable ascii char)
        fn get_ascii_byte(&mut self) -> Option<u8>;
        /// get bytes (printable ascii word)
        fn get_ascii_bytes(&mut self, vec: &mut Vec<u8>);
        /// get chars (printable ascii word)
        fn get_ascii_chars(&mut self, vec: &mut Vec<char>);
        /// get line bytes (sp+printable ascii)
        fn get_ascii_line_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (trimed sp+printable ascii)
        fn get_ascii_line_bytes_trim(&mut self, vec: &mut Vec<u8>);
        /// get bytes (printable utf8 word)
        fn get_utf8_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (sp+printable utf8)
        fn get_utf8_line_bytes(&mut self, vec: &mut Vec<u8>);
        /// get line bytes (trimed sp+printable utf8)
        fn get_utf8_line_bytes_trim(&mut self, vec: &mut Vec<u8>);
    }
    impl<T: Iterator<Item = u8>> ProconParse for T {
        fn parse_uint<
            U: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = U>
                + std::ops::Add<Output = U>
                + std::ops::Sub<Output = U>
                + std::ops::Mul<Output = U>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> U {
            loop {
                match self.next() {
                    Some(c @ b'0'..=b'9') => {
                        let mut x = U::from(c.wrapping_sub(b'0'));
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(U::from(10)).add(U::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(_) => continue,
                    None => unreachable!(),
                }
            }
        }
        fn parse_iint<
            I: Copy
                + std::cmp::Ord
                + std::ops::BitAnd<Output = I>
                + std::ops::Add<Output = I>
                + std::ops::Sub<Output = I>
                + std::ops::Mul<Output = I>
                + std::ops::Neg<Output = I>
                + std::convert::From<u8>,
        >(
            &mut self,
        ) -> I {
            loop {
                match self.next() {
                    Some(c @ b'0'..=b'9') => {
                        let mut x = I::from(c.wrapping_sub(b'0'));
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(I::from(10)).add(I::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(b'-') => {
                        let mut x = if let Some(c @ b'0'..=b'9') = self.next() {
                            I::from(c.wrapping_sub(b'0')).neg()
                        } else {
                            unreachable!();
                        };
                        while let Some(c @ b'0'..=b'9') = self.next() {
                            x = x.mul(I::from(10)).sub(I::from(c.wrapping_sub(b'0')));
                        }
                        break x;
                    }
                    Some(_) => continue,
                    None => unreachable!(),
                }
            }
        }
        fn parse_byte(&mut self) -> Option<u8> {
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => break Some(c),
                    Some(_) => continue,
                    None => break None,
                }
            }
        }
        fn parse_bytes(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => {
                        v.push(c);
                        while let Some(c @ b'!'..=b'~') = self.next() {
                            v.push(c);
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
        fn parse_line_bytes(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b' '..=b'~') => {
                        v.push(c);
                        while let Some(c @ b' '..=b'~') = self.next() {
                            v.push(c);
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
        fn parse_line_bytes_trim(&mut self) -> Vec<u8> {
            let mut v = vec![];
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => {
                        v.push(c);
                        while let Some(c @ b' '..=b'~') = self.next() {
                            v.push(c);
                        }
                        while v.last() == Some(&b' ') {
                            v.pop();
                        }
                        break v;
                    }
                    Some(_) => continue,
                    None => break v,
                }
            }
        }
    }
    impl<R: std::io::BufRead> ProconBytes for ProconIBufIter<R> {
        /// get bytes vector
        fn get_bytes_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<u8>, f: &mut F) {
            if !self.skipuntil_bytes_fn(f) {
                return;
            }
            let begin_ptr = self.ptr;
            let mut ptr = self.ptr;
            loop {
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(begin_ptr, ptr_offset_u8(ptr, begin_ptr))
                    });
                    break;
                }
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(begin_ptr, ptr_offset_u8(ptr, begin_ptr))
                    });
                    return;
                }
            }
            if unsafe { !self.inner_read() } {
                return;
            }
            ptr = self.ptr;
            loop {
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(self.raw, ptr_offset_u8(ptr, self.raw))
                    });
                    return;
                }
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    vec.extend_from_slice(unsafe {
                        std::slice::from_raw_parts(self.raw, self.len)
                    });
                    if unsafe { !self.inner_read() } {
                        return;
                    }
                    ptr = self.ptr;
                }
            }
        }
        fn get_ascii_chars_fn<F: Fn(u8) -> bool>(&mut self, vec: &mut Vec<char>, f: &mut F) {
            if !self.skipuntil_bytes_fn(f) {
                return;
            }
            let begin_ptr = self.ptr;
            let mut ptr = self.ptr;
            loop {
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, begin_ptr) };
                    vec.reserve(len);
                    let mut p = begin_ptr;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    break;
                }
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, begin_ptr) };
                    vec.reserve(len);
                    let mut p = begin_ptr;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    return;
                }
            }
            if unsafe { !self.inner_read() } {
                return;
            }
            ptr = self.ptr;
            loop {
                if !f(unsafe { *ptr }) {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, self.raw) };
                    vec.reserve(len);
                    let mut p = self.raw;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    return;
                }
                unsafe {
                    ptr = ptr.add(1);
                }
                if ptr == self.end {
                    self.ptr = ptr;
                    let len = unsafe { ptr_offset_u8(ptr, self.raw) };
                    vec.reserve(len);
                    let mut p = self.raw;
                    while p != ptr {
                        vec.push(unsafe { *p } as char);
                        p = unsafe { p.add(1) };
                    }
                    if unsafe { !self.inner_read() } {
                        return;
                    }
                    ptr = self.ptr;
                }
            }
        }
        fn get_ascii_byte(&mut self) -> Option<u8> {
            loop {
                match self.next() {
                    Some(c @ b'!'..=b'~') => break Some(c),
                    Some(_) => continue,
                    None => break None,
                }
            }
        }
        fn get_ascii_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b'!'..=b'~').contains(&c))
        }
        fn get_ascii_chars(&mut self, vec: &mut Vec<char>) {
            self.get_ascii_chars_fn(vec, &mut |c| (b'!'..=b'~').contains(&c))
        }
        fn get_ascii_line_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b' '..=b'~').contains(&c))
        }
        fn get_ascii_line_bytes_trim(&mut self, vec: &mut Vec<u8>) {
            self.skipuntil_bytes_fn(&mut |c| (b'!'..=b'~').contains(&c));
            self.get_bytes_fn(vec, &mut |c| (b' '..=b'~').contains(&c));
            while vec.last() == Some(&b' ') {
                vec.pop();
            }
        }
        fn get_utf8_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b'!'..=0xf4).contains(&c))
        }
        fn get_utf8_line_bytes(&mut self, vec: &mut Vec<u8>) {
            self.get_bytes_fn(vec, &mut |c| (b' '..=0xf4).contains(&c))
        }
        fn get_utf8_line_bytes_trim(&mut self, vec: &mut Vec<u8>) {
            self.skipuntil_bytes_fn(&mut |c| (b'!'..=0xf4).contains(&c));
            self.get_bytes_fn(vec, &mut |c| (b' '..=0xf4).contains(&c));
            while vec.last() == Some(&b' ') {
                vec.pop();
            }
        }
    }
    /// Insufficient write buffer size causes undefined operation.
    pub struct ProconWriteBuffer(*mut u8, Vec<u8>);
    impl ProconWriteBuffer {
        pub fn with_capacity(capacity: usize) -> Self {
            let mut b = Vec::<u8>::with_capacity(capacity);
            let ptr = b.as_mut_ptr();
            Self(ptr, b)
        }
        fn decision(&mut self) {
            let bptr = self.1.as_mut_ptr();
            unsafe { self.1.set_len((self.0 as usize) - (bptr as usize)) };
        }
        pub fn reserve(&mut self, additional: usize) {
            self.decision();
            self.1.reserve(additional);
            self.0 = self.1.as_mut_ptr();
        }
        pub fn reserve_exact(&mut self, additional: usize) {
            self.decision();
            self.1.reserve_exact(additional);
            self.0 = self.1.as_mut_ptr();
        }
        pub fn uint<U>(&mut self, d: U)
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            proconwritebuf_uint(&mut self.0, d);
        }
        pub fn uint_sp<U>(&mut self, s: &[U])
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d);
                }
            }
            self.0 = p;
        }
        pub fn uint_splf<U>(&mut self, s: &[U])
        where
            U: Copy
                + std::cmp::Ord
                + std::ops::Div<Output = U>
                + std::ops::Rem<Output = U>
                + std::convert::From<u8>
                + std::convert::Into<u128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn usize(&mut self, d: usize) {
            proconwritebuf_uint(&mut self.0, d as u64);
        }
        pub fn usize_sp(&mut self, s: &[usize]) {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d as u64);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d as u64);
                }
            }
            self.0 = p;
        }
        pub fn usize_splf(&mut self, s: &[usize]) {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_uint(&mut p, d as u64);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_uint(&mut p, d as u64);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn iint<I>(&mut self, d: I)
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>,
        {
            proconwritebuf_iint(&mut self.0, d);
        }
        pub fn iint_sp<I>(&mut self, s: &[I])
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_iint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_iint(&mut p, d);
                }
            }
            self.0 = p;
        }
        pub fn iint_splf<I>(&mut self, s: &[I])
        where
            I: Copy
                + std::cmp::Ord
                + std::ops::Neg<Output = I>
                + std::ops::Div<Output = I>
                + std::ops::Rem<Output = I>
                + std::convert::From<i8>
                + std::convert::Into<i128>
                + std::convert::TryInto<u8>,
        {
            let mut p = self.0;
            let mut it = s.iter();
            if let Some(&d) = it.next() {
                proconwritebuf_iint(&mut p, d);
                for &d in it {
                    proconwritebuf_sp(&mut p);
                    proconwritebuf_iint(&mut p, d);
                }
            }
            proconwritebuf_lf(&mut p);
            self.0 = p;
        }
        pub fn sp(&mut self) {
            proconwritebuf_sp(&mut self.0);
        }
        pub fn lf(&mut self) {
            proconwritebuf_lf(&mut self.0);
        }
        pub fn bytes(&mut self, s: &[u8]) {
            proconwritebuf_bytes(&mut self.0, s);
        }
        pub fn str(&mut self, s: &str) {
            proconwritebuf_str(&mut self.0, s);
        }
        pub fn string(&mut self, s: &String) {
            proconwritebuf_string(&mut self.0, s);
        }
        pub fn write_all<W>(&mut self, out: &mut W)
        where
            W: std::io::Write,
        {
            self.decision();
            let _ = out.write_all(self.1.as_slice());
            self.1.clear();
            self.0 = self.1.as_mut_ptr();
        }
    }
    pub fn proconwritebuf_uint<U>(p: &mut *mut u8, mut d: U)
    where
        U: Copy
            + std::cmp::Ord
            + std::ops::Div<Output = U>
            + std::ops::Rem<Output = U>
            + std::convert::From<u8>
            + std::convert::Into<u128>,
    {
        unsafe {
            let bptr = *p;
            let mut cptr = bptr;
            if d != U::from(0) {
                while d != U::from(0) {
                    let (q, r) = (d / U::from(10), d % U::from(10));
                    d = q;
                    *cptr = b'0' + U::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = bptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else {
                *cptr = b'0';
                *p = cptr.add(1);
            }
        };
    }
    pub fn proconwritebuf_iint<I>(p: &mut *mut u8, mut d: I)
    where
        I: Copy
            + std::cmp::Ord
            + std::ops::Neg<Output = I>
            + std::ops::Div<Output = I>
            + std::ops::Rem<Output = I>
            + std::convert::From<i8>
            + std::convert::Into<i128>,
    {
        unsafe {
            let bptr = *p;
            let mut cptr = bptr;
            if d > I::from(0) {
                while d != I::from(0) {
                    let (q, r) = (d / I::from(10), d % I::from(10));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = bptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else if d < I::from(0) {
                *cptr = b'-';
                cptr = cptr.add(1);
                let mptr = cptr;
                {
                    let (q, r) = (-(d / I::from(10)), -(d % I::from(10)));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                while d != I::from(0) {
                    let (q, r) = (d / I::from(10), d % I::from(10));
                    d = q;
                    *cptr = b'0' + I::into(r) as u8;
                    cptr = cptr.add(1);
                }
                *p = cptr;
                let mut lptr = mptr;
                let mut rptr = cptr.sub(1);
                while (lptr as usize) < (rptr as usize) {
                    let (dr, dl) = (*lptr, *rptr);
                    *lptr = dl;
                    *rptr = dr;
                    lptr = lptr.add(1);
                    rptr = rptr.sub(1);
                }
            } else {
                *cptr = b'0';
                *p = cptr.add(1);
            }
        };
    }
    pub fn proconwritebuf_sp(p: &mut *mut u8) {
        *p = unsafe {
            **p = b' ';
            (*p).add(1)
        }
    }
    pub fn proconwritebuf_lf(p: &mut *mut u8) {
        *p = unsafe {
            **p = b'\n';
            (*p).add(1)
        }
    }
    pub fn proconwritebuf_bytes(p: &mut *mut u8, bytes: &[u8]) {
        *p = unsafe {
            let len = bytes.len();
            std::ptr::copy_nonoverlapping(bytes.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
    pub fn proconwritebuf_str(p: &mut *mut u8, s: &str) {
        *p = unsafe {
            let len = s.len();
            std::ptr::copy_nonoverlapping(s.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
    pub fn proconwritebuf_string(p: &mut *mut u8, s: &String) {
        *p = unsafe {
            let len = s.len();
            std::ptr::copy_nonoverlapping(s.as_ptr(), *p, len);
            (*p).add(len)
        };
    }
}

Submission Info

Submission Time
Task E - Don't Isolate Elements
User mizarjp
Language Rust (1.42.0)
Score 500
Code Size 41006 Byte
Status AC
Exec Time 11 ms
Memory 2212 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 500 / 500
Status
AC × 3
AC × 30
Set Name Test Cases
Sample example0.txt, example1.txt, example2.txt
All example0.txt, example1.txt, example2.txt, hand0.txt, hand1.txt, hand2.txt, hand3.txt, random0.txt, random1.txt, random10.txt, random11.txt, random12.txt, random13.txt, random14.txt, random15.txt, random16.txt, random17.txt, random18.txt, random19.txt, random2.txt, random20.txt, random21.txt, random22.txt, random3.txt, random4.txt, random5.txt, random6.txt, random7.txt, random8.txt, random9.txt
Case Name Status Exec Time Memory
example0.txt AC 8 ms 2172 KiB
example1.txt AC 1 ms 2036 KiB
example2.txt AC 1 ms 2192 KiB
hand0.txt AC 2 ms 1992 KiB
hand1.txt AC 2 ms 2084 KiB
hand2.txt AC 2 ms 2088 KiB
hand3.txt AC 9 ms 2168 KiB
random0.txt AC 6 ms 2152 KiB
random1.txt AC 10 ms 2112 KiB
random10.txt AC 9 ms 2076 KiB
random11.txt AC 9 ms 2104 KiB
random12.txt AC 7 ms 2084 KiB
random13.txt AC 11 ms 2184 KiB
random14.txt AC 6 ms 2024 KiB
random15.txt AC 7 ms 2200 KiB
random16.txt AC 8 ms 2012 KiB
random17.txt AC 6 ms 2088 KiB
random18.txt AC 6 ms 2128 KiB
random19.txt AC 6 ms 2192 KiB
random2.txt AC 10 ms 2096 KiB
random20.txt AC 7 ms 2180 KiB
random21.txt AC 7 ms 2212 KiB
random22.txt AC 8 ms 2008 KiB
random3.txt AC 6 ms 2188 KiB
random4.txt AC 7 ms 2152 KiB
random5.txt AC 9 ms 2108 KiB
random6.txt AC 10 ms 2032 KiB
random7.txt AC 6 ms 2020 KiB
random8.txt AC 7 ms 2128 KiB
random9.txt AC 11 ms 2104 KiB