use std::io::BufRead;
use std::str::FromStr;
use std::fmt;
use std::str;
use std::collections::HashMap;

struct InputScanner<R: BufRead> {
    reader: R,
    buf: Vec<u8>, // Should never be empty
    pos: usize,   // Should never be out of bounds as long as the input ends with '\n'
}

impl<R: BufRead> InputScanner<R> {
    fn new(reader: R, capacity: usize) -> Self {
        InputScanner {
            reader: reader,
            buf: Vec::with_capacity(capacity),
            pos: 0,
        }
    }

    #[inline]
    fn next<T: FromStr>(&mut self) -> T
    where
        T::Err: fmt::Debug,
    {
        if self.buf.is_empty() {
            self._read_next_line();
        }
        let mut start = None;
        loop {
            match (self.buf[self.pos], start.is_some()) {
                (b' ', true) | (b'\n', true) => break,
                (_, true) | (b' ', false) => self.pos += 1,
                (b'\n', false) => self._read_next_line(),
                (_, false) => start = Some(self.pos),
            }
        }
        let target = &self.buf[start.unwrap()..self.pos];
        unsafe { str::from_utf8_unchecked(target) }.parse().unwrap()
    }

    #[inline]
    fn _read_next_line(&mut self) {
        self.pos = 0;
        self.buf.clear();
        if self.reader.read_until(b'\n', &mut self.buf).unwrap() == 0 {
            panic!("Reached EOF");
        }
    }
}

fn main() {
    let stdin = std::io::stdin();
    let mut scanner = InputScanner::new(stdin.lock(), 10000);
    let n: i32 = scanner.next();
    let m: i32 = scanner.next();
    let a: Vec<i32> = (0..n).map(|_| scanner.next()).collect();
    let b: Vec<i32> = (0..m).map(|_| scanner.next()).collect();

    let row_map: HashMap<i32, i32> = a.iter().enumerate().map(|(i, &x)| (x, i as i32)).collect();
    let col_map: HashMap<i32, i32> = b.iter().enumerate().map(|(i, &x)| (x, i as i32)).collect();

    let md = 1000000007;
    let res = if row_map.len() < a.len() || col_map.len() < b.len() {
        0
    } else {
        let mut covered_rows = 0;
        let mut covered_cols = 0;
        let mut res: i64 = 1;
        let mut cross = 0;
        for x in (1..(n*m+1)).rev() {
            let r = row_map.get(&x);
            let c = col_map.get(&x);
            match (r, c) {
                (Some(_), Some(_)) => {
                    covered_rows += 1;
                    covered_cols += 1;
                    cross += 1;
                },
                (Some(_), None) => {
                    res = (res * covered_cols) % md;
                    cross += 1;
                    covered_rows += 1;
                },
                (None, Some(_)) => {
                    res = (res * covered_rows) % md;
                    cross += 1;
                    covered_cols += 1;
                },
                (None, None) => {
                    let v = covered_cols * covered_rows - cross;
                    if v <= 0 {
                        res = 0;
                        break;
                    }
                    res = (res * v) % md;
                    cross += 1;
                }
            }
        };
        res
    };
    println!("{}", res)
}


Measured memory_bytes: 4352