use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::BTreeSet;
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split(' ').map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
enum Road {
    Street {x: i32, low: i32, high: i32},
    Avenue{y:i32, left: i32, right: i32}
}
impl Road {
    fn cross_point(&self, that: Road) -> Option<Position> {
        match (*self, that) {
            (Road::Street{x: x, low: low, high: high}, Road::Avenue{y: y, left: left, right: right}) if low <= y && y <= high && left <= x && x <= right => Some(Position{x: x, y: y}),
            (Road::Avenue{y: y, left: left, right: right}, Road::Street{x: x, low: low, high: high}) if low <= y && y <= high && left <= x && x <= right => Some(Position{x: x, y: y}),
            _ => None
        }
    }
    fn new(x1: i32, y1: i32, x2: i32, y2: i32) -> Road {
        if x1 == x2 {
            Road::Street{x: x1, low: min(y1, y2), high: max(y1, y2)}
        }else {
            Road::Avenue{y: y1, left: min(x1, x2), right: max(x1, x2)}
        }
    }
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
enum Dir {
    North, East, South, West
}
impl Dir {
    fn all_dir() -> Vec<Dir> {
        vec![Dir::North, Dir::East, Dir::South, Dir::West]
    }
    fn turn_right(&self) -> Dir {
        match *self {
            Dir::North => Dir::East,
            Dir::East => Dir::South,
            Dir::South => Dir::West,
            Dir::West => Dir::North,
        }
    }
    fn turn_left(&self) -> Dir {
        match *self {
            Dir::North => Dir::West,
            Dir::East => Dir::North,
            Dir::South => Dir::East,
            Dir::West => Dir::South,
        }
    }
    fn is_horizontal(&self) -> bool {
        match *self {
            Dir::West | Dir::East => true,
            _ => false,
        }
    }
    fn is_vertical(&self) -> bool {
        match *self {
            Dir::North | Dir::South => true,
            _ => false,
        }
    }
}
impl FromStr for Dir {
    type Err = ();
    fn from_str(s: &str) -> std::result::Result<Self, <Self as std::str::FromStr>::Err> { 
        match s {
            "N" => Ok(Dir::North),
            "E" => Ok(Dir::East),
            "S" => Ok(Dir::South),
            "W" => Ok(Dir::West),
            _ => Err(()),
        }
    }
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct Position {
    x: i32, y: i32
}
impl Add for Position {
    type Output = Position;
    fn add(self, rhs: Position) -> <Self as std::ops::Add<Position>>::Output { 
        Position{x: self.x + rhs.x, y: self.y + rhs.y}
     }
}
impl Position {
    fn move_to(&self, dir: Dir) -> Position {
        match dir {
            Dir::North => Position{x: self.x, y: self.y + 1},
            Dir::East => Position{x: self.x + 1, y: self.y},
            Dir::South => Position{x: self.x, y: self.y - 1},
            Dir::West => Position{x: self.x - 1, y: self.y},
        }
    }
}
impl PartialOrd for Position {
    fn partial_cmp(&self, rhs: &Position) -> std::option::Option<std::cmp::Ordering> { 
        Some(self.cmp(rhs))
     }
}
impl Ord for Position {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        self.x.cmp(&rhs.x).then(self.y.cmp(&rhs.y))    
    }
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
struct Car {
    position: Position, dir: Dir
}
impl Car {
    fn next_state(&self) -> Car {
        Car{position: self.position.move_to(self.dir), dir: self.dir}
    }
    fn turn(&self) -> Vec<Car> {
        vec![*self, Car{position: self.position, dir: self.dir.turn_left()}, Car{position: self.position, dir: self.dir.turn_right()}]
    }
    fn is_on_road(&self, road: Road) -> bool {
        match road {
            Road::Street{x: x, low: low, high: high} => self.dir.is_vertical() && self.position.x == x && low <= self.position.y && self.position.y <= high ,
            Road::Avenue{y: y, left: left, right: right} => self.dir.is_horizontal() && self.position.y == y && left <= self.position.x && self.position.x <= right,
        }
    }
}

fn main() {
    read!(n: usize, x0: i32, y0: i32, log_count: i32);
    read_map!{
        roads: [{
            read!(x1: i32, y1: i32, x2: i32, y2: i32);
            Road::new(x1, y1, x2, y2)
        }; n]
    }
    let mut cross_point = BTreeSet::new();
    for i in 0 .. n {
        for j in 0 .. i {
            if let Some(cp) = roads[i].cross_point(roads[j]) {
                cross_point.insert(cp);
            }
        }
    }
    freeze!(cross_point);
    let mut current_state = BTreeSet::new();
    for car in Dir::all_dir().into_iter().map(|dir| Car{position: Position{x: x0, y: y0}, dir: dir}) {
        if let Some(road) = roads.iter().find(|&road| car.is_on_road(*road)) {
            current_state.insert((car, road));
        }
    }
    for _ in 0 .. log_count {
        read!(dist: i32, dir: Dir);
        for _ in 1 .. dist {
            let mut next_state = BTreeSet::new();
            for &(car, road) in &current_state {
                let next = car.next_state();
                if !next.is_on_road(*road) {continue;}
                if cross_point.contains(&next.position) {
                    for next in next.turn() {
                        if let Some(road) = roads.iter().find(|&road| next.is_on_road(*road)) {
                            next_state.insert((next, road));
                        }
                    }
                }else {
                    if let Some(road) = roads.iter().find(|&road| next.is_on_road(*road)) {
                        next_state.insert((next, road));
                    }
                }
            }
            current_state = next_state;
        }
        let mut next_state = BTreeSet::new();
        for &(car, road) in &current_state {
            let next = car.next_state();
            if !next.is_on_road(*road){continue;}
            if cross_point.contains(&next.position) {
                for turned in next.turn() {
                    if car.dir != dir && turned.dir != dir {continue;}
                    if let Some(road) = roads.iter().find(|&road| turned.is_on_road(*road)) {
                        let next = turned.next_state();
                        if !next.is_on_road(*road) {continue;}
                        next_state.insert((turned, road));
                    }
                }
            }else if next.dir == dir {
                if let Some(road) = roads.iter().find(|&road| next.is_on_road(*road)) {
                    next_state.insert((next, road));
                }
            }
        }
        current_state = next_state;
    }
    let results = current_state.into_iter().map(|(car, _)| car.position).collect::<BTreeSet<_>>();
    for pos in results {

        println!("{} {}", pos.x, pos.y);
    }
}



Measured memory_bytes: 5072