#define _USE_MATH_DEFINES
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>

using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int64, int64> ii;
const int INF = 1 << 30;
const int MOD = 1e9 + 7;

const int N = 1e5 + 10;
const int M = N * 6;
int64 x[N], y[N];
int cnt[N];

struct Point {
  int64 x, y;
  int idx;
};

struct Node {
  int a, b;
  Node *left, *right;
};

Node pool[M], *last;
vector<int> e[M];

Node* build(const vector<Point>& p, int a, int b) {
  Node* cur = last++;
  cur->a = a;
  cur->b = b;
  if (a + 1 == b) {
    e[cur - pool].push_back(p[a].idx);
    return cur;
  }
  cur->left = build(p, a, (a + b) / 2);
  cur->right = build(p, (a + b) / 2, b);
  e[cur - pool].push_back(cur->left - pool);
  e[cur - pool].push_back(cur->right - pool);
  return cur;
}

struct cmp_x {
  bool operator ()(const Point& a, const Point& b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
  }
};

struct cmp_y {
  bool operator ()(const Point& a, const Point& b) {
    return a.y < b.y || (a.y == b.y && a.x < b.x);
  }
};

void query(Node* cur, int L, int R, vector<int>& nodes) {
  if (cur->a >= L && cur->b <= R) {
    nodes.push_back(cur - pool);
    return;
  }
  if ((cur->a + cur->b) / 2 > L) query(cur->left, L, R, nodes);
  if ((cur->a + cur->b) / 2 < R) query(cur->right, L, R, nodes);
}

int dfn[M], low[M];
int scc[M];

int stamp;
stack<int> S;
bool instack[M];

void DFS(int u) {
  low[u] = dfn[u] = stamp++;
  S.push(u);
  instack[u] = true;
  for (auto& v : e[u]) {
    if (dfn[v] == 0) {
      DFS(v);
      low[u] = min(low[u], low[v]);
    } else if (instack[v]) {
      low[u] = min(low[u], dfn[v]);
    }
  }
  if (low[u] == dfn[u]) {
    while (true) {
      int v = S.top();
      scc[v] = u;
      instack[v] = false;
      S.pop();
      if (v == u) break;
    }
  }
}

int main() {
  int n, u, v;
  scanf("%d%d%d", &n, &u, &v);
  --u; --v;
  vector<Point> a(n), b(n);
  set<ii> C;
  for (int i = 0; i < n; ++i) {
    int X, Y;
    scanf("%d%d", &X, &Y);
    x[i] = a[i].x = X + Y;
    y[i] = a[i].y = X - Y;
    a[i].idx = i;
    b[i] = a[i];
    C.insert({x[i], y[i]});
    // trace(x[i], y[i]);
  }
  int d = max(abs(x[u] - x[v]), abs(y[u] - y[v]));
  // trace(d);
  sort(a.begin(), a.end(), cmp_x());
  sort(b.begin(), b.end(), cmp_y());

  last = pool + n;
  Node* root_a = build(a, 0, n);
  Node* root_b = build(b, 0, n);

  for (int i = 0; i < n; ++i) {
    {
      int L = lower_bound(a.begin(), a.end(), Point{x[i] - d, y[i] - d}, cmp_x()) - a.begin();
      int R = upper_bound(a.begin(), a.end(), Point{x[i] - d, y[i] + d}, cmp_x()) - a.begin();
      vector<int> nodes;
      if (L < R) query(root_a, L, R, nodes);
      for (auto& it : nodes) {
        e[i].push_back(it);
      }
      cnt[i] += R - L;
    }
    {
      int L = lower_bound(a.begin(), a.end(), Point{x[i] + d, y[i] - d}, cmp_x()) - a.begin();
      int R = upper_bound(a.begin(), a.end(), Point{x[i] + d, y[i] + d}, cmp_x()) - a.begin();
      vector<int> nodes;
      if (L < R) query(root_a, L, R, nodes);
      for (auto& it : nodes) {
        e[i].push_back(it);
      }
      cnt[i] += R - L;
    }
    {
      int L = lower_bound(b.begin(), b.end(), Point{x[i] - d, y[i] - d}, cmp_y()) - b.begin();
      int R = upper_bound(b.begin(), b.end(), Point{x[i] + d, y[i] - d}, cmp_y()) - b.begin();
      vector<int> nodes;
      if (L < R) query(root_b, L, R, nodes);
      for (auto& it : nodes) {
        e[i].push_back(it);
      }
      cnt[i] += R - L;
    }
    {
      int L = lower_bound(b.begin(), b.end(), Point{x[i] - d, y[i] + d}, cmp_y()) - b.begin();
      int R = upper_bound(b.begin(), b.end(), Point{x[i] + d, y[i] + d}, cmp_y()) - b.begin();
      vector<int> nodes;
      if (L < R) query(root_b, L, R, nodes);
      for (auto& it : nodes) {
        e[i].push_back(it);
      }
      cnt[i] += R - L;
    }
    if (C.find({x[i] - d, y[i] - d}) != C.end()) --cnt[i];
    if (C.find({x[i] - d, y[i] + d}) != C.end()) --cnt[i];
    if (C.find({x[i] + d, y[i] - d}) != C.end()) --cnt[i];
    if (C.find({x[i] + d, y[i] + d}) != C.end()) --cnt[i];
    // trace(i, cnt[i]);
  }
  int m = last - pool;
  stamp = 1;
  for (int i = 0; i < m; ++i) {
    if (!dfn[i]) DFS(i);
  }
  assert(scc[u] == scc[v]);
  int64 ret = 0;
  for (int i = 0; i < n; ++i) {
    if (scc[i] == scc[u]) {
      ret += cnt[i];
    }
  }
  printf("%lld\n", ret / 2);
  return 0;
}


Measured memory_bytes: 84096