Problem:
Score : 600 points

Problem Statement

Given are an integer N and arrays S, T, U, and V, each of length N.
Construct an N×N matrix a that satisfy the following conditions:

a_{i,j} is an integer.

0 \leq a_{i,j} \lt 2^{64}.

If S_{i} = 0, the bitwise AND of the elements in the i-th row is U_{i}.

If S_{i} = 1, the bitwise OR of the elements in the i-th row is U_{i}.

If T_{i} = 0, the bitwise AND of the elements in the i-th column is V_{i}.

If T_{i} = 1, the bitwise OR of the elements in the i-th column is V_{i}.

However, there may be cases where no matrix satisfies the conditions.

Constraints

All values in input are integers.

1 \leq N \leq 500

0 \leq S_{i} \leq 1

0 \leq T_{i} \leq 1

0 \leq U_{i} \lt 2^{64}

0 \leq V_{i} \lt 2^{64}

Input

Input is given from Standard Input in the following format:

N
S_{1} S_{2} ... S_{N}
T_{1} T_{2} ... T_{N}
U_{1} U_{2} ... U_{N}
V_{1} V_{2} ... V_{N}

Output

If there exists a matrix that satisfies the conditions, print one such matrix in the following format:

a_{1,1} ... a_{1,N}
:
a_{N,1} ... a_{N,N}

Note that any matrix satisfying the conditions is accepted.

If no matrix satisfies the conditions, print -1.

Sample Input 1

2
0 1
1 0
1 1
1 0

Sample Output 1

1 1
1 0

In Sample Input 1, we need to find a matrix such that:

the bitwise AND of the elements in the 1-st row is 1;

the bitwise OR of the elements in the 2-nd row is 1;

the bitwise OR of the elements in the 1-st column is 1;

the bitwise AND of the elements in the 2-nd column is 0.

Sample Input 2

2
1 1
1 0
15 15
15 11

Sample Output 2

15 11
15 11

Solution in Rust (1.42.0) (judge verdict: Accepted)

use proconio::input;

fn f(tbl: &mut Vec<Vec<Option<bool>>>, st: &Vec<Vec<u64>>, uv: &Vec<Vec<u64>>, i: usize) -> bool {
    let n = st[0].len();

    // (And && true) || (Or && false) の行を確定する
    for &flipped in [false, true].iter() {
        let ir = if flipped { 1 } else { 0 };
        for (y, (&ro, &rvbits)) in st[ir].iter().zip(uv[ir].iter()).enumerate() {
            let rv = (rvbits >> i) & 1;
            // (And (0) && true (1)) || (Or (1) && false (0))
            if ro != rv {
                let v = rv == 1;
                // その行はすべて rv
                for x in 0..n {
                    let (yt, xt) = if flipped { (x, y) } else { (y, x) };
                    match tbl[yt][xt] {
                        Some(b) if b != v => return false,
                        _ => tbl[yt][xt] = Some(v),
                    }
                }
            }
        }
    }

    // (And && false) || (Or && true) のうち確定できる行を確定する
    // 確定できる行: 未確定列が 1 列かつ、少なくとも 1 列は必要な列がない行
    for _ in 0..2 {
        for &flipped in [false, true].iter() {
            let ir = if flipped { 1 } else { 0 };
            for (y, (&ro, &rvbits)) in st[ir].iter().zip(uv[ir].iter()).enumerate() {
                let rv = (rvbits >> i) & 1;
                // (And (0) && false (0)) || (Or (1) && true (1))
                if ro == rv {
                    let v = rv == 1;
                    // その行は少なくとも 1 列の rv を含む
                    let mut ok = false;
                    let mut yxs = vec![];
                    for x in 0..n {
                        let (yt, xt) = if flipped { (x, y) } else { (y, x) };
                        match tbl[yt][xt] {
                            None => yxs.push((yt, xt)),
                            Some(b) if b == v => ok = true,
                            _ => {}
                        }
                    }
                    if !ok {
                        match yxs.len() {
                            0 => return false,
                            1 => {
                                let (yt, xt) = yxs[0];
                                tbl[yt][xt] = Some(v);
                            }
                            _ => {} // ignore
                        }
                    }
                }
            }
        }
    }

    // 残っているのは (And && false) || (Or && true) のうち
    // - 未確定 1 列以上の true / false どちらでも良い行 (ok 行なので無視する)
    // - 未確定 2 列以上の true / false どちらかでないといけない行
    // 2 列以上の場所については false / true を両方含めることで条件を満たせる
    let mut oks = vec![vec![false; n]; 2];
    for &flipped in [false, true].iter() {
        let ir = if flipped { 1 } else { 0 };
        for y in 0..n {
            let mut ok = true;
            for x in 0..n {
                let (yt, xt) = if flipped { (x, y) } else { (y, x) };
                if tbl[yt][xt].is_none() {
                    ok = false;
                    break;
                }
            }
            oks[ir][y] = ok;
        }
    }
    let mut cy = 0;
    for y in 0..n {
        let mut cx = 0;
        if oks[0][y] {
            continue;
        }
        for x in 0..n {
            if oks[1][x] {
                continue;
            }
            tbl[y][x] = Some((cy + cx) % 2 == 1);
            cx += 1;
        }
        cy += 1;
    }

    true
}

fn main() {
    input! {
        n: usize,
        st: [[u64; n]; 2],
        uv: [[u64; n]; 2]
    };
    let mut ans = vec![vec![0_u64; n]; n];
    for i in 0..64 {
        let mut tbl = vec![vec![None; n]; n];
        if !f(&mut tbl, &st, &uv, i) {
            println!("-1");
            return;
        }

        for y in 0..n {
            for x in 0..n {
                if tbl[y][x] == Some(true) {
                    ans[y][x] |= 1_u64 << i;
                }
            }
        }
    }
    for y in 0..n {
        for x in 0..n {
            print!("{}{}", ans[y][x], if x == n - 1 { "\n" } else { " " });
        }
    }
}