mod utils {
    use std::error::Error;
    use std::io::stdin;
    use std::str::FromStr;

    #[allow(dead_code)]
    pub fn read_line<T>() -> Result<Vec<T>, Box<Error>>
    where
        T: FromStr,
        T::Err: 'static + Error,
    {
        let mut line = String::new();
        let _ = stdin().read_line(&mut line)?;
        let parsed_line = line.split_whitespace()
            .map(|x| x.parse::<T>())
            .collect::<Result<Vec<T>, T::Err>>()?;

        Ok(parsed_line)
    }

    #[allow(dead_code)]
    pub fn read_lines<T>(n: usize) -> Result<Vec<Vec<T>>, Box<Error>>
    where
        T: FromStr,
        T::Err: 'static + Error,
    {
        (0..n).map(|_| read_line()).collect()
    }
}

struct Solver {
    board: Vec<Vec<String>>,
}

impl Solver {
    fn cell_to_int(s: String) -> usize {
        if s == "Q".to_owned() {
            1
        } else {
            0
        }
    }

    fn print_board(&self) -> () {
        println!(
            "{}",
            self.board
                .iter()
                .map(|row| row.join(""))
                .collect::<Vec<_>>()
                .join("\n")
        );
    }
    fn validate_vh(&self) -> bool {
        let mut counter_v = vec![0 as usize; 8];
        let mut counter_h = vec![0 as usize; 8];
        for (i, row) in self.board.iter().enumerate() {
            for (j, cell) in row.iter().enumerate() {
                counter_h[i] = counter_h[i] + Solver::cell_to_int(cell.to_string());
                counter_v[j] = counter_v[j] + Solver::cell_to_int(cell.to_string());
            }
        }

        counter_v.iter().all(|&x| x <= 1) && counter_h.iter().all(|&x| x <= 1)
    }

    fn validate_d(&self) -> bool {
        let mut counter_ij = vec![0; 8 + 7];
        let mut counter_ji = vec![0; 8 + 7];

        for (i, row) in self.board.iter().enumerate() {
            for (j, cell) in row.iter().enumerate() {
                let c = Solver::cell_to_int(cell.to_string());
                counter_ij[(7 + i - j) as usize] = counter_ij[(7 + i - j) as usize] + c;
                counter_ji[i + j] = counter_ji[i + j] + c;
            }
        }

        counter_ij.iter().all(|&x| x <= 1) && counter_ji.iter().all(|&x| x <= 1)
    }

    fn validate_board(&self) -> bool {
        self.validate_vh() && self.validate_d()
    }

    fn solve_rec(&mut self, i: usize) -> bool {
        if !self.validate_board() {
            return false;
        }

        if i == 8 {
            return true;
        }

        let queen_exists = self.board[i]
            .iter()
            .find(|&x| *x == "Q".to_owned())
            .is_some();

        if queen_exists {
            return self.solve_rec(i + 1);
        } else {
            for j in 0..8 {
                self.board[i][j] = "Q".to_owned();

                if self.solve_rec(i + 1) {
                    return true;
                }

                self.board[i][j] = ".".to_owned();
            }
        }
        false
    }
}

fn solve() -> Result<(), Box<std::error::Error>> {
    let k = utils::read_line::<usize>()?[0];
    let queens = utils::read_lines::<usize>(k)?;

    let mut board = vec![vec![".".to_owned(); 8]; 8];
    for q in queens {
        board[q[0]][q[1]] = "Q".to_owned();
    }

    let mut solver = Solver { board: board };
    solver.solve_rec(0);
    solver.print_board();

    Ok(())
}

fn main() {
    match solve() {
        Err(err) => panic!("{}", err),
        _ => (),
    };
}



Measured memory_bytes: 5060