use core::ops::Bound::Excluded;
use core::ops::Bound::Included;
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<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>>()
}
fn read_tabulate<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
}
macro_rules! define {
    () => {};
    ($($token:tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        define_iter!(iter, $($token)*);
    };
}
macro_rules! define_iter {
    ($iter:expr) =>{};
    ($iter:expr,) =>{};
    ($iter:expr, $id:ident:$t:tt $($tail:tt)*) => {
        let $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*);
    };
    ($iter:expr, mut $id:ident:$t:tt $($tail:tt)*) => {
        let mut $id: $t = $iter.next().unwrap().parse().ok().expect("Can't Parse");
        define_iter!($iter, $($tail)*)
    };
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
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(Clone, Copy, Eq, PartialEq, Debug)]
struct Coordinate {
    x: i32, y: i32
}
impl Coordinate {
    fn intercept45(&self) -> i32 {
        self.y - self.x
    }
    fn intercept135(&self) -> i32 {
        self.y + self.x
    }
    fn manhattan_distance(&self, that: &Coordinate) -> i32 {
        (self.x - that.x).abs() + (self.y - that.y).abs()
    }
}
fn lower_bound<T, F: Fn(&T) -> bool>(array: &Vec<T>, predicate: F) -> usize {
    let mut min = 0usize;
    let mut max = array.len();
    while min < max {
        let mid = (min + max) >> 1;
        if predicate(&array[mid]) {
            min = mid + 1;
        }else {
            max = mid;
        }
    }
    max
}
fn lower_bound_with_range<T, F: Fn(&T) -> bool> (array: &Vec<T>, mut from: usize, mut until: usize, predicate: F) -> usize {
    while from < until {
        let mid = (from + until) >> 1;
        if predicate(&array[mid]) {
            from = mid + 1;
        }else {
            until = mid;
        }
    }
    until
}
struct Range {
    from: usize, until: usize
}
fn up(base: Coordinate, distance: i32, vec: &Vec<usize>, holes: &Vec<Coordinate>) -> Range {
    let lower_i = lower_bound(&vec, |&i| holes[i].intercept45() < base.intercept45() + distance);
    let upper_i = lower_bound(&vec, |&i| holes[i].intercept45() <= base.intercept45() + distance);
    let lower_x = lower_bound_with_range(&vec, lower_i, upper_i, |&i| holes[i].x + distance < base.x);
    let upper_x = lower_bound_with_range(&vec, lower_x, upper_i, |&i| holes[i].x <= base.x);
    Range{from: lower_x, until: upper_x}
}
fn right(base: Coordinate, distance: i32, vec: &Vec<usize>, holes: &Vec<Coordinate>) -> Range {
    let lower_i = lower_bound(&vec, |&i| holes[i].intercept135() - distance < base.intercept135());
    let upper_i = lower_bound(&vec, |&i| holes[i].intercept135() - distance <= base.intercept135());
    let lower_x = lower_bound_with_range(&vec, lower_i, upper_i, |&i| holes[i].x <= base.x);
    let upper_x = lower_bound_with_range(&vec, lower_x, upper_i, |&i| holes[i].x < base.x + distance);
    Range{from: lower_x, until: upper_x}
}
fn down(base: Coordinate, distance: i32, vec: &Vec<usize>, holes: &Vec<Coordinate>) -> Range {
    let lower_i = lower_bound(&vec, |&i| holes[i].intercept45() < base.intercept45() - distance);
    let upper_i = lower_bound(&vec, |&i| holes[i].intercept45() <= base.intercept45() - distance);
    let lower_x = lower_bound_with_range(&vec, lower_i, upper_i, |&i| holes[i].x < base.x);
    let upper_x = lower_bound_with_range(&vec, lower_x, upper_i, |&i| holes[i].x <= base.x + distance);
    Range{from: lower_x, until: upper_x}
}
fn left(base: Coordinate, distance: i32, vec: &Vec<usize>, holes: &Vec<Coordinate>) -> Range {
    let lower_i = lower_bound(&vec, |&i| holes[i].intercept135() < base.intercept135() - distance);
    let upper_i = lower_bound(&vec, |&i| holes[i].intercept135() <= base.intercept135() - distance);
    let lower_x = lower_bound_with_range(&vec, lower_i, upper_i, |&i| holes[i].x + distance <= base.x);
    let upper_x = lower_bound_with_range(&vec, lower_x, upper_i, |&i| holes[i].x < base.x);
    Range{from: lower_x, until: upper_x}
}
fn move_to(from: usize, until: usize, map: &Vec<usize>, src: &mut BTreeSet<usize>, dst: &mut Vec<usize>) {
    for i in src.range((Included(from), Excluded(until))).copied().collect::<Vec<_>>() {
        dst.push(map[i]);
        src.remove(&i);
    }
}
fn neighbor(base: Coordinate, distance: i32, i45: &Vec<usize>, i135: &Vec<usize>, holes: &Vec<Coordinate>, i45_set: &mut BTreeSet<usize>, i135_set: &mut BTreeSet<usize>) -> (usize, Vec<usize>) {
    let mut result = Vec::new();
    let mut sum = 0usize;
    match up(base, distance, i45, holes) {
        Range{from, until} => {
            move_to(from, until, i45, i45_set, &mut result);
            sum += until - from;
        }
    }
    match down(base, distance, i45, holes) {
        Range{from, until} => {
            move_to(from, until, i45, i45_set, &mut result);
            sum += until - from;
        }
    }
    match right(base, distance, i135, holes) {
        Range{from, until} => {
            move_to(from, until, i135, i135_set, &mut result);
            sum += until - from;
        }
    }
    match left(base, distance, i135, holes) {
        Range{from, until} => {
            move_to(from, until, i135, i135_set, &mut result);
            sum += until - from;
        }
    }
    (sum, result)
}
fn main() {
    define! {
        n: usize
        a: usize
        b: usize
    }
    let mut holes = Vec::with_capacity(n);
    for _ in 0 .. n {
        define! {
            x: i32
            y: i32
        }
        holes.push(Coordinate{x, y});
    }
    let mut intercept45 = (0 .. n).collect::<Vec<_>>();
    intercept45.sort_by(|&i, &j| holes[i].intercept45().cmp(&holes[j].intercept45()).then(holes[i].x.cmp(&holes[j].x)));
    let mut intercept135 = (0 .. n).collect::<Vec<_>>();
    intercept135.sort_by(|&i, &j| holes[i].intercept135().cmp(&holes[j].intercept135()).then(holes[i].x.cmp(&holes[j].x)));
    let mut in_stack = vec![false; n];
    let mut stack = Vec::new();
    in_stack[a - 1] = true; in_stack[b - 1] = true;
    stack.push(a - 1); stack.push(b - 1);
    let distance = holes[a - 1].manhattan_distance(&holes[b - 1]);
    let mut result = 0usize;
    let mut i45_set = (0 .. n).collect::<BTreeSet<_>>();
    let mut i135_set = i45_set.clone();
    while let Some(top) = stack.pop() {
        let (count, next) = neighbor(holes[top], distance, &intercept45, &intercept135, &holes, &mut i45_set, &mut i135_set);
        //println!("top: {}, count: {}, next: {:?}", top, count, next);
        result += count;
        for i in next {
            if !in_stack[i] {
                in_stack[i] = true;
                stack.push(i);
            }
        }
    }
    println!("{}", result >> 1);
}

Measured memory_bytes: 9928