Problem p03858 (C++)

Buggy submission (status: Runtime Error):
#define _USE_MATH_DEFINES
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

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 << 2;
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;
}


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

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;
}