Problem:
Score : 700 points

Problem Statement

Snuke is playing a puzzle game.
In this game, you are given a rectangular board of dimensions R × C, filled with numbers. Each integer i from 1 through N is written twice, at the coordinates (x_{i,1},y_{i,1}) and (x_{i,2},y_{i,2}).

The objective is to draw a curve connecting the pair of points where the same integer is written, for every integer from 1 through N.
Here, the curves may not go outside the board or cross each other.

Determine whether this is possible.

Constraints

1 ≤ R,C ≤ 10^8

1 ≤ N ≤ 10^5

0 ≤ x_{i,1},x_{i,2} ≤ R(1 ≤ i ≤ N)

0 ≤ y_{i,1},y_{i,2} ≤ C(1 ≤ i ≤ N)

All given points are distinct.

All input values are integers.

Input

Input is given from Standard Input in the following format:

R C N
x_{1,1} y_{1,1} x_{1,2} y_{1,2}
:
x_{N,1} y_{N,1} x_{N,2} y_{N,2}

Output

Print YES if the objective is achievable; print NO otherwise.

Sample Input 1

4 2 3
0 1 3 1
1 1 4 1
2 0 2 2

Sample Output 1

YES

The above figure shows a possible solution.

Sample Input 2

2 2 4
0 0 2 2
2 0 0 1
0 2 1 2
1 1 2 1

Sample Output 2

NO

Sample Input 3

5 5 7
0 0 2 4
2 3 4 5
3 5 5 2
5 5 5 4
0 3 5 1
2 2 4 4
0 5 4 1

Sample Output 3

YES

Sample Input 4

1 1 2
0 0 1 1
1 0 0 1

Sample Output 4

NO

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

use std::collections::{BTreeSet, VecDeque};

fn main() {
    let mut sc = Scanner::new();
    let r = sc.usize_read();
    let c = sc.usize_read();
    let n = sc.usize_read();

    let on_line = |x: usize, y: usize| x == 0 || x == r || y == 0 || y == c;

    let mut upper_x = vec![];
    let mut upper_y = vec![];
    let mut lower_x = vec![];
    let mut lower_y = vec![];

    for i in 0..n {
        let x1 = sc.usize_read();
        let y1 = sc.usize_read();
        let x2 = sc.usize_read();
        let y2 = sc.usize_read();
        if on_line(x1, y1) && on_line(x2, y2) {
            let mut push = |i: usize, x: usize, y: usize| {
                if x == 0 {
                    lower_x.push((y, i));
                } else if x == r {
                    upper_x.push((y, i));
                } else if y == 0 {
                    lower_y.push((x, i));
                } else if y == c {
                    upper_y.push((x, i));
                } else {
                    panic!();
                };
            };

            push(i, x1, y1);
            push(i, x2, y2);
        }
    }

    upper_x.sort();
    lower_x.sort();
    upper_y.sort();
    lower_y.sort();

    let mut line = vec![];
    for &(_, i) in &lower_x {
        line.push(i);
    }
    for &(_, i) in &upper_y {
        line.push(i);
    }
    for &(_, i) in upper_x.iter().rev() {
        line.push(i);
    }
    for &(_, i) in lower_y.iter().rev() {
        line.push(i);
    }

    let mut stack = VecDeque::new();
    let mut set = BTreeSet::new();
    for &i in &line {
        if stack.is_empty() || head(&mut stack) != i {
            if set.contains(&i) {
                println!("NO");
                return;
            }

            stack.push_front(i);
            set.insert(i);
        } else {
            stack.pop_front();
        }
    }

    println!("YES");
}

fn head<T: Clone>(stack: &mut VecDeque<T>) -> T {
    let h = stack.pop_front().unwrap();
    stack.push_front(h.clone());
    h
}

struct Scanner {
    ptr: usize,
    length: usize,
    buf: Vec<u8>,
    small_cache: Vec<u8>,
}

#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner {
        Scanner {
            ptr: 0,
            length: 0,
            buf: vec![0; 1024],
            small_cache: vec![0; 1024],
        }
    }

    fn load(&mut self) {
        use std::io::Read;
        let mut s = std::io::stdin();
        self.length = s.read(&mut self.buf).unwrap();
    }

    fn byte(&mut self) -> u8 {
        if self.ptr >= self.length {
            self.ptr = 0;
            self.load();
            if self.length == 0 {
                self.buf[0] = b'\n';
                self.length = 1;
            }
        }

        self.ptr += 1;
        return self.buf[self.ptr - 1];
    }

    fn is_space(b: u8) -> bool {
        b == b'\n' || b == b'\r' || b == b'\t' || b == b' '
    }

    fn read_vec<T>(&mut self, n: usize) -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        (0..n).map(|_| self.read()).collect()
    }

    fn usize_read(&mut self) -> usize {
        self.read()
    }

    fn read<T>(&mut self) -> T
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut b = self.byte();
        while Scanner::is_space(b) {
            b = self.byte();
        }

        for pos in 0..self.small_cache.len() {
            self.small_cache[pos] = b;
            b = self.byte();
            if Scanner::is_space(b) {
                return String::from_utf8_lossy(&self.small_cache[0..(pos + 1)])
                    .parse()
                    .unwrap();
            }
        }

        let mut v = self.small_cache.clone();
        while !Scanner::is_space(b) {
            v.push(b);
            b = self.byte();
        }
        return String::from_utf8_lossy(&v).parse().unwrap();
    }
}