Problem p03802 (C++)

Buggy submission (status: Runtime Error):

#include <algorithm>
#include <cstdio>
#include <map>
#include <stack>
#include <vector>

using namespace std;

void Get_Val(int &Ret) {
  Ret = 0;
  char ch;
  while (ch = getchar(), ch > '9' || ch < '0')
    ;
  do {
    (Ret *= 10) += ch - '0';
  } while (ch = getchar(), ch >= '0' && ch <= '9');
}

namespace G {
const int Max_V(10050 * 10);
const int Max_E(10050 * 100);
int V, Head[Max_V], Total, To[Max_E], Next[Max_E];
inline void Add_Edge(const int &s, const int &t) {
  ++Total, To[Total] = t, Next[Total] = Head[s], Head[s] = Total;
}
inline int rev(const int &x) { return (x <= V) ? (x + V) : (x - V); }
inline void Link(const int &a, const int &b) {
  Add_Edge(rev(a), b), Add_Edge(rev(b), a);
}
int dfsclock, Pre[Max_V], Lowlink[Max_V], scctot, sccno[Max_V];
stack<int> S;
void clear() {
  for (int i = 1; i <= (V << 1); ++i)
    Head[i] = Pre[i] = Lowlink[i] = sccno[i] = 0;
  for (int i = 1; i <= Total; ++i)
    To[i] = Next[i] = 0;
  Total = dfsclock = scctot = 0;
}
void Tarjan(const int &u) {
  int v;
  Pre[u] = Lowlink[u] = ++dfsclock, S.push(u);
  for (int i = Head[u]; i; i = Next[i])
    if (!Pre[v = To[i]])
      Tarjan(v), Lowlink[u] = min(Lowlink[u], Lowlink[v]);
    else if (!sccno[v])
      Lowlink[u] = min(Lowlink[u], Pre[v]);
  if (Pre[u] == Lowlink[u]) {
    ++scctot;
    while (true) {
      v = S.top(), S.pop();
      sccno[v] = scctot;
      if (u == v)
        break;
    }
  }
}
bool check() {
  for (int i = 1; i <= (V << 1); ++i)
    if (!Pre[i])
      Tarjan(i);
  for (int i = 1; i <= V; ++i)
    if (sccno[i] == sccno[i + V])
      return false;
  return true;
}
} // namespace G

const int Max_N(10050);
const int Max_M(20050);

int N, M, X[Max_N], Y[Max_N], P[Max_M << 1];
vector<int> V[Max_M], Pre[Max_M], Suf[Max_M];
map<int, int> S;

void init() {
  Get_Val(N);
  for (int i = 1; i <= N; ++i)
    Get_Val(X[i]), Get_Val(Y[i]), S[X[i]], S[Y[i]];
  for (map<int, int>::iterator it = S.begin(); it != S.end(); ++it)
    P[it->second = ++M] = it->first;
  for (int i = 1; i <= N; ++i)
    X[i] = S[X[i]], Y[i] = S[Y[i]];
}

#define LCH (segt[cur].lch)
#define RCH (segt[cur].rch)

struct node {
  int lch, rch;
};
int tot, root, Pos[Max_M];
node segt[Max_M << 1];

void build_tree(int &cur, const int &LEFT, const int &RIGHT) {
  if (!cur)
    segt[++tot] = segt[cur], cur = tot;
  if (LEFT == RIGHT) {
    Pos[LEFT] = cur;
    return;
  }
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  build_tree(LCH, LEFT, MID), build_tree(RCH, MID + 1, RIGHT);
}

void dfs(const int &cur, const int &LEFT, const int &RIGHT) {
  if (LEFT == RIGHT)
    return;
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  G::Link(G::rev(N + LCH), N + cur), G::Link(G::rev(N + RCH), N + cur);
  dfs(LCH, LEFT, MID), dfs(RCH, MID + 1, RIGHT);
}

void Link(const int &cur, const int &LEFT, const int &RIGHT, const int &l,
          const int &r, const int &p) {
  if (LEFT == l && RIGHT == r) {
    G::Link(G::rev(N + cur), G::rev(p));
    return;
  }
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  if (r <= MID)
    Link(LCH, LEFT, MID, l, r, p);
  else if (l > MID)
    Link(RCH, MID + 1, RIGHT, l, r, p);
  else
    Link(LCH, LEFT, MID, l, MID, p), Link(RCH, MID + 1, RIGHT, MID + 1, r, p);
}

bool check(const int &D) {
  if (D == 0)
    return true;
  G::clear();
  dfs(root, 1, M);
  for (int p = 1, l, r, mid; p <= M; ++p) {
    for (int j = 0; j != V[p].size(); ++j)
      G::Link(G::rev(V[p][j]), N + Pos[p]);
    for (int j = 0; j != V[p].size(); ++j) {
      G::Link(G::rev(V[p][j]), Suf[p][j]);
      G::Link(G::rev(V[p][j]), Pre[p][j]);
      if (j - 1 >= 0) {
        G::Link(G::rev(V[p][j]), G::rev(Pre[p][j - 1]));
        G::Link(G::rev(Pre[p][j - 1]), Pre[p][j]);
      }
      if (j + 1 < V[p].size()) {
        G::Link(G::rev(V[p][j]), G::rev(Suf[p][j + 1]));
        G::Link(G::rev(Suf[p][j + 1]), Suf[p][j]);
      }
    }
    l = 1, r = p + 1;
    while (l < r) {
      mid = l + ((r - l) >> 1);
      if (P[p] - P[mid] < D)
        r = mid;
      else
        l = mid + 1;
    }
    if (l <= p - 1)
      Link(root, 1, M, l, p - 1, N + Pos[p]);
    l = p, r = M + 1;
    while (l < r) {
      mid = l + ((r - l) >> 1);
      if (P[mid] - P[p] < D)
        l = mid + 1;
      else
        r = mid;
    }
    if (p + 1 <= (--l))
      Link(root, 1, M, p + 1, l, N + Pos[p]);
  }
  return G::check();
}

void work() {
  build_tree(root, 1, M);
  G::V = N + tot;
  for (int i = 1; i <= N; ++i)
    V[X[i]].push_back(i), V[Y[i]].push_back(-i);
  for (int p = 1; p <= M; ++p) {
    for (int j = 0; j != V[p].size(); ++j)
      Pre[p].push_back(++G::V);
    for (int j = 0; j != V[p].size(); ++j)
      Suf[p].push_back(++G::V);
  }
  for (int p = 1; p <= M; ++p)
    for (int j = 0; j != V[p].size(); ++j)
      if (V[p][j] > 0)
        V[p][j] = V[p][j];
      else
        V[p][j] = G::rev(-V[p][j]);
  int l(0), r(1000000000), mid;
  while (l < r) {
    mid = l + ((r - l) >> 1);
    if (check(mid))
      l = mid + 1;
    else
      r = mid;
  }
  printf("%d", l - 1);
}

int main() {
  init();
  work();
  return 0;
}

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <map>
#include <stack>
#include <vector>

using namespace std;

void Get_Val(int &Ret) {
  Ret = 0;
  char ch;
  while (ch = getchar(), ch > '9' || ch < '0')
    ;
  do {
    (Ret *= 10) += ch - '0';
  } while (ch = getchar(), ch >= '0' && ch <= '9');
}

namespace G {
const int Max_V(10050 * 30);
const int Max_E(10050 * 300);
int V, Head[Max_V], Total, To[Max_E], Next[Max_E];
inline void Add_Edge(const int &s, const int &t) {
  ++Total, To[Total] = t, Next[Total] = Head[s], Head[s] = Total;
}
inline int rev(const int &x) { return (x <= V) ? (x + V) : (x - V); }
inline void Link(const int &a, const int &b) {
  Add_Edge(rev(a), b), Add_Edge(rev(b), a);
}
int dfsclock, Pre[Max_V], Lowlink[Max_V], scctot, sccno[Max_V];
stack<int> S;
void clear() {
  for (int i = 1; i <= (V << 1); ++i)
    Head[i] = Pre[i] = Lowlink[i] = sccno[i] = 0;
  for (int i = 1; i <= Total; ++i)
    To[i] = Next[i] = 0;
  Total = dfsclock = scctot = 0;
}
void Tarjan(const int &u) {
  int v;
  Pre[u] = Lowlink[u] = ++dfsclock, S.push(u);
  for (int i = Head[u]; i; i = Next[i])
    if (!Pre[v = To[i]])
      Tarjan(v), Lowlink[u] = min(Lowlink[u], Lowlink[v]);
    else if (!sccno[v])
      Lowlink[u] = min(Lowlink[u], Pre[v]);
  if (Pre[u] == Lowlink[u]) {
    ++scctot;
    while (true) {
      v = S.top(), S.pop();
      sccno[v] = scctot;
      if (u == v)
        break;
    }
  }
}
bool check() {
  for (int i = 1; i <= (V << 1); ++i)
    if (!Pre[i])
      Tarjan(i);
  for (int i = 1; i <= V; ++i)
    if (sccno[i] == sccno[i + V])
      return false;
  return true;
}
} // namespace G

const int Max_N(10050);
const int Max_M(20050);

int N, M, X[Max_N], Y[Max_N], P[Max_M << 1];
vector<int> V[Max_M], Pre[Max_M], Suf[Max_M];
map<int, int> S;

void init() {
  Get_Val(N);
  for (int i = 1; i <= N; ++i)
    Get_Val(X[i]), Get_Val(Y[i]), S[X[i]], S[Y[i]];
  for (map<int, int>::iterator it = S.begin(); it != S.end(); ++it)
    P[it->second = ++M] = it->first;
  for (int i = 1; i <= N; ++i)
    X[i] = S[X[i]], Y[i] = S[Y[i]];
}

#define LCH (segt[cur].lch)
#define RCH (segt[cur].rch)

struct node {
  int lch, rch;
};
int tot, root, Pos[Max_M];
node segt[Max_M << 1];

void build_tree(int &cur, const int &LEFT, const int &RIGHT) {
  if (!cur)
    segt[++tot] = segt[cur], cur = tot;
  if (LEFT == RIGHT) {
    Pos[LEFT] = cur;
    return;
  }
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  build_tree(LCH, LEFT, MID), build_tree(RCH, MID + 1, RIGHT);
}

void dfs(const int &cur, const int &LEFT, const int &RIGHT) {
  if (LEFT == RIGHT)
    return;
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  G::Link(G::rev(N + LCH), N + cur), G::Link(G::rev(N + RCH), N + cur);
  dfs(LCH, LEFT, MID), dfs(RCH, MID + 1, RIGHT);
}

void Link(const int &cur, const int &LEFT, const int &RIGHT, const int &l,
          const int &r, const int &p) {
  if (LEFT == l && RIGHT == r) {
    G::Link(G::rev(N + cur), G::rev(p));
    return;
  }
  int MID = LEFT + ((RIGHT - LEFT) >> 1);
  if (r <= MID)
    Link(LCH, LEFT, MID, l, r, p);
  else if (l > MID)
    Link(RCH, MID + 1, RIGHT, l, r, p);
  else
    Link(LCH, LEFT, MID, l, MID, p), Link(RCH, MID + 1, RIGHT, MID + 1, r, p);
}

bool check(const int &D) {
  if (D == 0)
    return true;
  G::clear();
  dfs(root, 1, M);
  for (int p = 1, l, r, mid; p <= M; ++p) {
    for (int j = 0; j != V[p].size(); ++j)
      G::Link(G::rev(V[p][j]), N + Pos[p]);
    for (int j = 0; j != V[p].size(); ++j) {
      G::Link(G::rev(V[p][j]), Suf[p][j]);
      G::Link(G::rev(V[p][j]), Pre[p][j]);
      if (j - 1 >= 0) {
        G::Link(G::rev(V[p][j]), G::rev(Pre[p][j - 1]));
        G::Link(G::rev(Pre[p][j - 1]), Pre[p][j]);
      }
      if (j + 1 < V[p].size()) {
        G::Link(G::rev(V[p][j]), G::rev(Suf[p][j + 1]));
        G::Link(G::rev(Suf[p][j + 1]), Suf[p][j]);
      }
    }
    l = 1, r = p + 1;
    while (l < r) {
      mid = l + ((r - l) >> 1);
      if (P[p] - P[mid] < D)
        r = mid;
      else
        l = mid + 1;
    }
    if (l <= p - 1)
      Link(root, 1, M, l, p - 1, N + Pos[p]);
    l = p, r = M + 1;
    while (l < r) {
      mid = l + ((r - l) >> 1);
      if (P[mid] - P[p] < D)
        l = mid + 1;
      else
        r = mid;
    }
    if (p + 1 <= (--l))
      Link(root, 1, M, p + 1, l, N + Pos[p]);
  }
  return G::check();
}

void work() {
  build_tree(root, 1, M);
  G::V = N + tot;
  for (int i = 1; i <= N; ++i)
    V[X[i]].push_back(i), V[Y[i]].push_back(-i);
  for (int p = 1; p <= M; ++p) {
    for (int j = 0; j != V[p].size(); ++j)
      Pre[p].push_back(++G::V);
    for (int j = 0; j != V[p].size(); ++j)
      Suf[p].push_back(++G::V);
  }
  for (int p = 1; p <= M; ++p)
    for (int j = 0; j != V[p].size(); ++j)
      if (V[p][j] > 0)
        V[p][j] = V[p][j];
      else
        V[p][j] = G::rev(-V[p][j]);
  int l(0), r(1000000000), mid;
  while (l < r) {
    mid = l + ((r - l) >> 1);
    if (check(mid))
      l = mid + 1;
    else
      r = mid;
  }
  printf("%d", l - 1);
}

int main() {
  init();
  work();
  return 0;
}