Problem: There are N pinholes on the xy-plane. The i-th pinhole is located at (x_i,y_i).

We will denote the Manhattan distance between the i-th and j-th pinholes as d(i,j)(=|x_i-x_j|+|y_i-y_j|).

You have a peculiar pair of compasses, called Manhattan Compass. This instrument always points at two of the pinholes. The two legs of the compass are indistinguishable, thus we do not distinguish the following two states: the state where the compass points at the p-th and q-th pinholes, and the state where it points at the q-th and p-th pinholes.

When the compass points at the p-th and q-th pinholes and d(p,q)=d(p,r), one of the legs can be moved so that the compass will point at the p-th and r-th pinholes.

Initially, the compass points at the a-th and b-th pinholes. Find the number of the pairs of pinholes that can be pointed by the compass.

Constraints

* 2≦N≦10^5
* 1≦x_i, y_i≦10^9
* 1≦a < b≦N
* When i ≠ j, (x_i, y_i) ≠ (x_j, y_j)
* x_i and y_i are integers.

Input

The input is given from Standard Input in the following format:


N a b
x_1 y_1
:
x_N y_N


Output

Print the number of the pairs of pinholes that can be pointed by the compass.

Examples

Input

5 1 2
1 1
4 3
6 1
5 5
4 8


Output

4


Input

6 2 3
1 3
5 3
3 5
8 4
4 7
2 5


Output

4


Input

8 1 2
1 5
4 3
8 2
4 7
8 8
3 3
6 6
4 8


Output

7

Solution (in JAVA):

Solution:
//package com.company;
// Always comment out package when submitting.
import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    public static class Task {
        public class Point {
            long[] coord = new long[2];
            int idx;

            public Point(int x, int y, int idx) {
                this.coord[0] = x + y;
                this.coord[1] = y - x;
                this.idx = idx;
            }

            public long dist(Point other) {
                return Math.max(Math.abs(coord[0] - other.coord[0]), Math.abs(coord[1] - other.coord[1]));
            }
        }

        public void solve(Scanner sc, PrintWriter pw) throws IOException {
            int n = sc.nextInt();
            int a = sc.nextInt() - 1;
            int b = sc.nextInt() - 1;
            Point[] points = new Point[n];
            for (int i = 0; i < n; i++) {
                int x = sc.nextInt();
                int y = sc.nextInt();
                points[i] = new Point(x, y, i);
            }
            long dist = points[a].dist(points[b]);
            Set<Integer>[] edges = new Set[n];
            for (int i = 0; i < n; i++) {
                edges[i] = new HashSet<>();
            }
            solve(points, dist, 0, edges, true);
            solve(points, dist, 1, edges, false);
            boolean[] visit = new boolean[n];
            Arrays.sort(points, new Comparator<Point>() {
                @Override
                public int compare(Point o1, Point o2) {
                    return o1.idx - o2.idx;
                }
            });
            dfs(edges, visit, a);

            int countI = 0;
            for (boolean bb: visit) if (bb) countI++;
            Point[] sbPoints = new Point[countI];
            countI = 0;
            for (int i = 0; i < n; i++) {
                if (visit[i]) sbPoints[countI++] = points[i];
            }
            long tot = 0;
            tot += solve(sbPoints, dist, 0, null, true);
            tot += solve(sbPoints, dist, 1, null, false);
            pw.println(tot);

        }

        public int binarySearchLow(Point[] points, int index, long coordinateVal, long minOtherVal, long maxOtherVal) {
            int sub = 1 - index;
            int lo = 0, hi = points.length;
            while (lo < hi - 1) {
                int mid = (lo + hi) >> 1;
                if (points[mid].coord[index] < coordinateVal) {
                    lo = mid + 1;
                } else if (points[mid].coord[index] > coordinateVal) {
                    hi = mid;
                } else if (points[mid].coord[sub] < minOtherVal) {
                    lo = mid + 1;
                } else {
                    hi = mid;
                }
            }
            for (int i = Math.max(0, lo - 5); i < Math.min(points.length, lo + 5); i++) {
                if (points[i].coord[index] == coordinateVal && points[i].coord[sub] >= minOtherVal && points[i].coord[sub] <= maxOtherVal) {
                    return i;
                }
            }
            return -1;
        }

        public int binarySearchHigh(Point[] points, int index, long coordinateVal, long minOtherVal, long maxOtherVal) {
            int sub = 1 - index;
            int lo = 0, hi = points.length;
            while (lo < hi - 1) {
                int mid = (lo + hi) >> 1;
                if (points[mid].coord[index] < coordinateVal) {
                    lo = mid + 1;
                } else if (points[mid].coord[index] > coordinateVal) {
                    hi = mid;
                } else if (points[mid].coord[sub] > maxOtherVal) {
                    hi = mid;
                } else {
                    lo = mid + 1;
                }
            }
            for (int i = Math.min(points.length, lo + 5) - 1; i >= Math.max(0, lo - 5); i--) {
                if (points[i].coord[index] == coordinateVal && points[i].coord[sub] >= minOtherVal && points[i].coord[sub] <= maxOtherVal) {
                    return i;
                }
            }
            return -1;
        }

        public void addEdge(Set<Integer>[] edges, int a, int b) {
            if (edges == null) return;
//            if (a < b){
                edges[a].add(b);
//            } else {
                edges[b].add(a);
//            }
        }

        public void dfs(Set<Integer>[] edges, boolean[] visit, int cur) {
            visit[cur] = true;
            for (int next: edges[cur]) if (!visit[next]) dfs(edges, visit, next);
        }

        public long solve(Point[] points, long dist, int index, Set<Integer>[] edges, boolean cS) {
            int sub = 1 - index;
            Arrays.sort(points, new Comparator<Point>() {
                @Override
                public int compare(Point o1, Point o2) {
                    if (o1.coord[index] == o2.coord[index]) return Long.compare(o1.coord[sub], o2.coord[sub]);
                    return Long.compare(o1.coord[index], o2.coord[index]);
                }
            });
            long count = 0;
            int fast = 0;
            for (int i = 0; i < points.length; i++) {
                long mm = points[i].coord[index];
                long kk = points[i].coord[sub];
                long cv = mm + dist;
                long minV = kk - dist;
                long maxV = kk + dist;
                if (!cS) {
                    minV++;
                    maxV--;
                }
                int nextLow = binarySearchLow(points, index, cv, minV, maxV);
                int nextLarge = binarySearchHigh(points, index, cv, minV, maxV);
                if ((nextLow == -1) != (nextLarge == -1)) {
                    throw new RuntimeException();
                }
                if (nextLarge < nextLow) throw new RuntimeException();
                if (nextLarge == -1) continue;
                count += nextLarge - nextLow + 1;
                addEdge(edges, points[i].idx, points[nextLow].idx);
                if (nextLow >= fast) {
                    for (int j = nextLow; j < nextLarge; j++) {
                        addEdge(edges, points[j].idx, points[j + 1].idx);
                    }
                    fast = nextLarge;
                } else if (nextLarge >= fast) {
                    for (int j = fast; j < nextLarge; j++) {
                        addEdge(edges, points[j].idx, points[j + 1].idx);
                    }
                    fast = nextLarge;
                }
            }
            return count;
        }

    }

    // template, actual code is in class Task.
    static long TIME_START, TIME_END;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
//        Scanner sc = new Scanner(new FileInputStream("Test.in"));
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));
//        PrintWriter pw = new PrintWriter(new FileOutputStream("Test.out"));

        Runtime runtime = Runtime.getRuntime();
        long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
        TIME_START = System.currentTimeMillis();
        Task t = new Task();
        t.solve(sc, pw);
        TIME_END = System.currentTimeMillis();
        long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
        pw.close();
//        System.err.println("Memory increased: " + (usedMemoryAfter - usedMemoryBefore) / 1000000);
//        System.err.println("Time used: " + (TIME_END - TIME_START) + ".");
    }

    // Faster IO with BufferedReader wrapped with Scanner
    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public Scanner(FileReader s) throws FileNotFoundException {
            br = new BufferedReader(s);
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }
}