Hướng dẫn giải của Hội Họa


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
use std::{convert::TryInto, fmt::Debug, io::*, iter::*, str::*};

fn main() {
    let mut stdin = stdin().lock();
    let mut writer = BufWriter::new(stdout());
    let mut read_line = || -> String {
        let mut line = String::new();
        stdin.read_line(&mut line).unwrap();
        line
    };

    let ntest = parse::<usize>(&read_line());
    for _ in 0..ntest {
        // eprintln!("==== test");
        let [n, m] = split_arr::<2, usize>(&read_line());
        let a = (0..n).map(|_| split_vec::<usize>(&read_line())).collect::<Vec<_>>();

        let mut r_next = (0..=n).map(|r| (r + 1) % (n + 1)).collect::<Vec<_>>();
        let mut r_prev = (0..=n).map(|r| (r + n) % (n + 1)).collect::<Vec<_>>();
        let mut c_next = (0..=m).map(|c| (c + 1) % (m + 1)).collect::<Vec<_>>();
        let mut c_prev = (0..=m).map(|c| (c + m) % (m + 1)).collect::<Vec<_>>();

        let mut r_cnt_sep = (0..n)
            .map(|r| (1..m).map(|c| (a[r][c] != a[r][c - 1]) as usize).sum::<usize>())
            .collect::<Vec<_>>();
        let mut c_cnt_sep = (0..m)
            .map(|c| (1..n).map(|r| (a[r][c] != a[r - 1][c]) as usize).sum::<usize>())
            .collect::<Vec<_>>();

        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
        enum Side {
            Row,
            Col,
        }

        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
        struct Op {
            side: Side,
            idx: usize,
            val: usize,
        }

        fn iter_link(next: &[usize], start: usize, end: usize) -> impl Iterator<Item = usize> + '_ {
            successors(Some(start), move |&i| Some(next[i])).take_while(move |&i| i != end)
        }

        let mut ans = Vec::<Op>::new();
        while r_next[n] != n && c_next[m] != m {
            if let Some((_, r)) = r_cnt_sep.iter().zip(0..).find(|&(&x, _)| x == 0) {
                let i = c_next[m];
                let prv = r_prev[r];
                let nxt = r_next[r];
                // eprintln!("Row {} has no separation, {}", r, i);
                ans.push(Op { side: Side::Row, idx: r, val: a[r][i] });
                r_cnt_sep[r] = m; // just to exclude from search
                for i in iter_link(&c_next, i, m) {
                    if prv != n && a[prv][i] != a[r][i] {
                        c_cnt_sep[i] -= 1;
                    }
                    if nxt != n && a[nxt][i] != a[r][i] {
                        c_cnt_sep[i] -= 1;
                    }
                    if nxt != n && prv != n && a[prv][i] != a[nxt][i] {
                        c_cnt_sep[i] += 1;
                    }
                }
                r_next[prv] = nxt;
                r_prev[nxt] = prv;
                continue;
            }

            if let Some((_, c)) = c_cnt_sep.iter().zip(0..).find(|&(&x, _)| x == 0) {
                let i = r_next[n];
                let prv = c_prev[c];
                let nxt = c_next[c];
                // eprintln!("Column {} has no separation, {}", c, i);
                ans.push(Op { side: Side::Col, idx: c, val: a[i][c] });
                c_cnt_sep[c] = n; // just to exclude from search
                for i in iter_link(&r_next, i, n) {
                    if prv != m && a[i][prv] != a[i][c] {
                        r_cnt_sep[i] -= 1;
                    }
                    if nxt != m && a[i][nxt] != a[i][c] {
                        r_cnt_sep[i] -= 1;
                    }
                    if nxt != m && prv != m && a[i][prv] != a[i][nxt] {
                        r_cnt_sep[i] += 1;
                    }
                }
                c_next[prv] = nxt;
                c_prev[nxt] = prv;
                continue;
            }

            break;
        }
        if r_next[n] != n && c_next[m] != m {
            writeln!(writer, "NO").unwrap();
            continue;
        }
        writeln!(writer, "YES").unwrap();
        writeln!(writer, "{}", ans.len()).unwrap();
        for &Op { side, idx, val } in ans.iter().rev() {
            match side {
                Side::Row => writeln!(writer, "0 {} {}", idx + 1, val).unwrap(),
                Side::Col => writeln!(writer, "1 {} {}", idx + 1, val).unwrap(),
            }
        }
    }
}

fn parse<T: FromStr>(s: &str) -> T {
    s.trim().parse::<T>().ok().unwrap()
}
fn split_vec<T: FromStr>(s: &str) -> Vec<T> {
    s.trim().split_whitespace().map(parse).collect::<Vec<_>>()
}
fn split_arr<const N: usize, T: FromStr>(s: &str) -> [T; N] {
    split_vec::<T>(s).try_into().ok().unwrap()
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.