Problem p03802 (C++)

Buggy submission (status: Runtime Error):
// 2sat.cpp
#include <iostream>
#include <vector>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef vector<int> vi;

// scc.cppのコピー
// 強連結成分分解 (Strongly Connected Component)
struct SCCGraph : public vector<vi> {

  vector<int> order; // 属する強連結成分の番号(トポロジカル順序になっている)
  vector<int> vs;    // 帰りがけ順
  vector<bool> used; // すでに調べたか

  using vector::vector; // 継承コンストラクタ
  SCCGraph(const vector<vi> &v)
      : vector::vector(v) {} // コピーコンストラクタを使用可能にする

  // a -> b の辺を追加する。push_back()でも同じ
  void add_edge(int a, int b) { (*this)[a].push_back(b); }

  // scc()で使う
  void dfs(int n, int k, vector<vi> &v, vector<vi> &rv) {
    used[n] = true;
    order[n] = k;
    for (auto t : v[n]) {
      rv[t].push_back(n); // 逆辺のグラフを作成
      if (!used[t])
        dfs(t, k, v, rv);
    }
    vs.push_back(n);
  }

  // 強連結成分分解を行う
  int scc() {
    int N = size();
    used.assign(N, false);
    order.resize(N);
    vs.clear();
    vector<vi> rG(N), tmp(N); // 辺を逆にしたグラフ用
    for (int n = 0; n < N; n++) {
      if (!used[n])
        dfs(n, n, (*this), rG);
    }
    used.assign(N, false);
    int k = 0; // 強連結成分の番号
    for (int i = vs.size() - 1; i >= 0; i--) {
      if (!used[vs[i]])
        dfs(vs[i], k++, rG, tmp);
    }
    return k;
  }

  // 属する強連結成分が同じかどうか判定
  bool find(int x, int y) { return order[x] == order[y]; }
};
// 関数としてsccを使う。戻り値は、各ノードが所属する強連結成分の番号
vector<int> scc(const vector<vi> &v) {
  SCCGraph g(v);
  g.scc();
  return g.order;
}

// 2-SAT
struct TwoSAT {
  SCCGraph graph;
  int N;
  vector<bool> val; // 結果

  TwoSAT(int n) : graph((n + 1) * 2), val(n + 1) { N = n; }

  void clear() {
    for (auto &&t : graph)
      t.clear();
  }

  // 辺( a -> b )を追加する。負の値は論理変数の否定(~a)を表す。
  void add_edge(int a, int b) {
    if (a < 0)
      a = N - a;
    if (b < 0)
      b = N - b;
    // cout << "--- add_edge: " << a << " -> " << b << endl;
    graph.add_edge(a, b);
  }

  // 論理式( a V b )
  // を追加する。a,bは、論理変数の番号(0以外の整数)。否定は負の値で表す。
  void add_or(int a, int b) {
    add_edge(-a, b);
    add_edge(-b, a);
  }

  // 判定を行う
  bool solve() {
    graph.scc();
    bool ret = true;
    for (int i = 1; i <= N; i++) {
      if (graph.order[i] == graph.order[N + i])
        ret = false;
      val[i] = (graph.order[i] > graph.order[N + i]);
    }
    return ret;
  }

  // 変数の値を取得する。
  bool value(int a) {
    if (a < 0)
      return !val[-a];
    return val[a];
  }
};

// 各ノードの情報
template <typename T, T INIT> struct node {
  T v, lazy;
  node() {
    v = INIT;
    lazy = 0;
  }
  // ノードの値の更新
  void merge(T vl, T vr) { v = min(vl, vr); }
  // ノードの値の更新(lazy適用)
  T add(int l, int r, T _v = 0) {
    T sum = lazy + _v;
    v += sum;
    lazy = 0;
    return sum;
  }
  // 遅延分の変更(加算)
  void addLazy(T v) { lazy += v; }
};

TwoSAT sat(40000);
const int SegOff = 20003;
void setRelation(int k, int v) {
  k += SegOff;
  v += SegOff;
  // cout << "setRelation: " << k << " " << v << endl;
  sat.add_or(-k, -v);
  // sat.add_edge( v, -k );
  // sat.add_edge( k, -v );
}

const int INF = 1e9 + 7;

template <typename T, typename NODE = node<T, INF>> class SegTree {
  // 遅延分の適応と伝播(現在のノードの値を確定させてLazyを伝搬させる)
  void propLazy(int a, int b, int k, T v = 0) {
    setRelation(k, N + v);
    // T lazy = data[k].add(a, b, v);
    // if( k < N ){
    //	data[k*2+0].addLazy(lazy);
    //	data[k*2+1].addLazy(lazy);
    // }
  }
  // セグメントツリーをたどる
  T prop(int l, int r, T v, int a, int b, int k = 1) {
    // 今いるノードの値を確定させる
    // propLazy(a, b, k);
    // たどる
    NODE nd; // 結果保存用(範囲外の場合は初期値が返る)
    if (l <= a && b <= r) {
      // 完全に範囲内の場合
      propLazy(a, b, k, v);
      return data[k].v;
    } else if (l < b && a < r) {
      // 中途半端に含まれる場合
      int m = (a + b) / 2;
      T vl = prop(l, r, v, a, m, k * 2);
      T vr = prop(l, r, v, m, b, k * 2 + 1);
      data[k].merge(data[k * 2].v, data[k * 2 + 1].v);
      nd.merge(vl, vr);
    }
    return nd.v;
  }

public:
  vector<NODE> data;
  int N;
  SegTree(int _N) {
    // _N <= (N = 2^k) を満たすNを見つける
    N = 1;
    while (N < _N)
      N <<= 1;
    data.resize(N * 2);
  }
  void pRelation() {
    // 子がTrueなら、親もTrue
    rep(i, N) if (i) {
      // cout << "pRelation: " << (SegOff + i*2) << " " << (SegOff + i) << endl;
      sat.add_edge(SegOff + i * 2, SegOff + i);
      sat.add_edge(SegOff + i * 2 + 1, SegOff + i);
      // sat.add_edge(SegOff + i, SegOff + i*2   );
      // sat.add_edge(SegOff + i, SegOff + i*2+1 );
    }
  }
  void cRelation(int i, int v) {
    int p = SegOff + N + i;
    // cout << "cRelation: " << p << " " << v << endl;
    // sat.add_or( p, v );
    // sat.add_or( -p, -v );
    sat.add_edge(p, v);
    sat.add_edge(v, p);
    sat.add_edge(-p, -v);
    sat.add_edge(-v, -p);
  }
  // セグメントツリーの更新(指定した場所の値をvに変更)
  void update(int l, T v) { prop(l, l + 1, v - get(l), 0, N); }
  // セグメントツリーの更新(範囲に加算)
  T add(int l, int r, T v) {
    // cout << "sg.add(): " << l << " " << r << " :" << v << endl;
    return prop(l, r, v, 0, N);
  }
  // 値を取得 [l,r)
  T get(int l, int r) { return prop(l, r, 0, 0, N); }
  // 値を取得 [l,l+1)
  T get(int l) { return prop(l, l + 1, 0, 0, N); }
};

// Atcoder ARC069 Flags (http://arc069.contest.atcoder.jp/tasks/arc069_d)
#include <algorithm>
#include <map>
typedef pair<int, int> pii;
int main() {
  int N;
  int x[2][10005];
  vector<pii> mp;
  SegTree<int> sg(20005);

  cin >> N;
  rep(i, N) {
    cin >> x[0][i] >> x[1][i];
    mp.emplace_back(x[0][i], i + 1);
    mp.emplace_back(x[1][i], -(i + 1));
  }
  sort(mp.begin(), mp.end());
  // cout << "sort" << endl;

  auto fn = [&](int m) {
    // cout << "fn " << m << endl;
    sat.clear();
    sg.pRelation();
    rep(i, mp.size()) { sg.cRelation(i, mp[i].second); }
    rep(i, mp.size()) {
      // down
      auto it =
          lower_bound(mp.begin(), mp.end(), pii(mp[i].first - m + 1, -INF));
      int pos = (it - mp.begin());
      sg.add(pos, i, i);
      // up
      it = lower_bound(mp.begin(), mp.end(), pii(mp[i].first + m, -INF));
      // it--;
      pos = (it - mp.begin());
      sg.add(i + 1, pos, i);
    }
    // cout << "setup finish" << endl;
    bool ret = sat.solve();
    // cout << "ret: " << ret << endl;
    return ret;
  };

  int l = 0, r = 1e9;
  while (r - l > 1) {
    int m = (l + r) / 2;
    if (fn(m)) {
      l = m;
    } else {
      r = m;
    }
  }

  cout << l << endl;

  return 0;
}

Fixed submission:
// 2sat.cpp
#include <iostream>
#include <vector>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef vector<int> vi;

// scc.cppのコピー
// 強連結成分分解 (Strongly Connected Component)
struct SCCGraph : public vector<vi> {

  vector<int> order; // 属する強連結成分の番号(トポロジカル順序になっている)
  vector<int> vs;    // 帰りがけ順
  vector<bool> used; // すでに調べたか

  using vector::vector; // 継承コンストラクタ
  SCCGraph(const vector<vi> &v)
      : vector::vector(v) {} // コピーコンストラクタを使用可能にする

  // a -> b の辺を追加する。push_back()でも同じ
  void add_edge(int a, int b) { (*this)[a].push_back(b); }

  // scc()で使う
  void dfs(int n, int k, vector<vi> &v, vector<vi> &rv) {
    used[n] = true;
    order[n] = k;
    for (auto t : v[n]) {
      rv[t].push_back(n); // 逆辺のグラフを作成
      if (!used[t])
        dfs(t, k, v, rv);
    }
    vs.push_back(n);
  }

  // 強連結成分分解を行う
  int scc() {
    int N = size();
    used.assign(N, false);
    order.resize(N);
    vs.clear();
    vector<vi> rG(N), tmp(N); // 辺を逆にしたグラフ用
    for (int n = 0; n < N; n++) {
      if (!used[n])
        dfs(n, n, (*this), rG);
    }
    used.assign(N, false);
    int k = 0; // 強連結成分の番号
    for (int i = vs.size() - 1; i >= 0; i--) {
      if (!used[vs[i]])
        dfs(vs[i], k++, rG, tmp);
    }
    return k;
  }

  // 属する強連結成分が同じかどうか判定
  bool find(int x, int y) { return order[x] == order[y]; }
};
// 関数としてsccを使う。戻り値は、各ノードが所属する強連結成分の番号
vector<int> scc(const vector<vi> &v) {
  SCCGraph g(v);
  g.scc();
  return g.order;
}

// 2-SAT
struct TwoSAT {
  SCCGraph graph;
  int N;
  vector<bool> val; // 結果

  TwoSAT(int n) : graph((n + 1) * 2), val(n + 1) { N = n; }

  void clear() {
    for (auto &&t : graph)
      t.clear();
  }

  // 辺( a -> b )を追加する。負の値は論理変数の否定(~a)を表す。
  void add_edge(int a, int b) {
    if (a < 0)
      a = N - a;
    if (b < 0)
      b = N - b;
    // cout << "--- add_edge: " << a << " -> " << b << endl;
    graph.add_edge(a, b);
  }

  // 論理式( a V b )
  // を追加する。a,bは、論理変数の番号(0以外の整数)。否定は負の値で表す。
  void add_or(int a, int b) {
    add_edge(-a, b);
    add_edge(-b, a);
  }

  // 判定を行う
  bool solve() {
    graph.scc();
    bool ret = true;
    for (int i = 1; i <= N; i++) {
      if (graph.order[i] == graph.order[N + i])
        ret = false;
      val[i] = (graph.order[i] > graph.order[N + i]);
    }
    return ret;
  }

  // 変数の値を取得する。
  bool value(int a) {
    if (a < 0)
      return !val[-a];
    return val[a];
  }
};

// 各ノードの情報
template <typename T, T INIT> struct node {
  T v, lazy;
  node() {
    v = INIT;
    lazy = 0;
  }
  // ノードの値の更新
  void merge(T vl, T vr) { v = min(vl, vr); }
  // ノードの値の更新(lazy適用)
  T add(int l, int r, T _v = 0) {
    T sum = lazy + _v;
    v += sum;
    lazy = 0;
    return sum;
  }
  // 遅延分の変更(加算)
  void addLazy(T v) { lazy += v; }
};

TwoSAT sat(90005);
const int SegOff = 20003;
void setRelation(int k, int v) {
  k += SegOff;
  v += SegOff;
  // cout << "setRelation: " << k << " " << v << endl;
  sat.add_or(-k, -v);
  // sat.add_edge( v, -k );
  // sat.add_edge( k, -v );
}

const int INF = 1e9 + 7;

template <typename T, typename NODE = node<T, INF>> class SegTree {
  // 遅延分の適応と伝播(現在のノードの値を確定させてLazyを伝搬させる)
  void propLazy(int a, int b, int k, T v = 0) {
    setRelation(k, N + v);
    // T lazy = data[k].add(a, b, v);
    // if( k < N ){
    //	data[k*2+0].addLazy(lazy);
    //	data[k*2+1].addLazy(lazy);
    // }
  }
  // セグメントツリーをたどる
  T prop(int l, int r, T v, int a, int b, int k = 1) {
    // 今いるノードの値を確定させる
    // propLazy(a, b, k);
    // たどる
    NODE nd; // 結果保存用(範囲外の場合は初期値が返る)
    if (l <= a && b <= r) {
      // 完全に範囲内の場合
      propLazy(a, b, k, v);
      return data[k].v;
    } else if (l < b && a < r) {
      // 中途半端に含まれる場合
      int m = (a + b) / 2;
      T vl = prop(l, r, v, a, m, k * 2);
      T vr = prop(l, r, v, m, b, k * 2 + 1);
      data[k].merge(data[k * 2].v, data[k * 2 + 1].v);
      nd.merge(vl, vr);
    }
    return nd.v;
  }

public:
  vector<NODE> data;
  int N;
  SegTree(int _N) {
    // _N <= (N = 2^k) を満たすNを見つける
    N = 1;
    while (N < _N)
      N <<= 1;
    data.resize(N * 2);
  }
  void pRelation() {
    // 子がTrueなら、親もTrue
    rep(i, N) if (i) {
      // cout << "pRelation: " << (SegOff + i*2) << " " << (SegOff + i) << endl;
      sat.add_edge(SegOff + i * 2, SegOff + i);
      sat.add_edge(SegOff + i * 2 + 1, SegOff + i);
      // sat.add_edge(SegOff + i, SegOff + i*2   );
      // sat.add_edge(SegOff + i, SegOff + i*2+1 );
    }
  }
  void cRelation(int i, int v) {
    int p = SegOff + N + i;
    // cout << "cRelation: " << p << " " << v << endl;
    // sat.add_or( p, v );
    // sat.add_or( -p, -v );
    sat.add_edge(p, v);
    sat.add_edge(v, p);
    sat.add_edge(-p, -v);
    sat.add_edge(-v, -p);
  }
  // セグメントツリーの更新(指定した場所の値をvに変更)
  void update(int l, T v) { prop(l, l + 1, v - get(l), 0, N); }
  // セグメントツリーの更新(範囲に加算)
  T add(int l, int r, T v) {
    // cout << "sg.add(): " << l << " " << r << " :" << v << endl;
    return prop(l, r, v, 0, N);
  }
  // 値を取得 [l,r)
  T get(int l, int r) { return prop(l, r, 0, 0, N); }
  // 値を取得 [l,l+1)
  T get(int l) { return prop(l, l + 1, 0, 0, N); }
};

// Atcoder ARC069 Flags (http://arc069.contest.atcoder.jp/tasks/arc069_d)
#include <algorithm>
#include <map>
typedef pair<int, int> pii;
int main() {
  int N;
  int x[2][10005];
  vector<pii> mp;
  SegTree<int> sg(20005);

  cin >> N;
  rep(i, N) {
    cin >> x[0][i] >> x[1][i];
    mp.emplace_back(x[0][i], i + 1);
    mp.emplace_back(x[1][i], -(i + 1));
  }
  sort(mp.begin(), mp.end());
  // cout << "sort" << endl;

  auto fn = [&](int m) {
    // cout << "fn " << m << endl;
    sat.clear();
    sg.pRelation();
    rep(i, mp.size()) { sg.cRelation(i, mp[i].second); }
    rep(i, mp.size()) {
      // down
      auto it =
          lower_bound(mp.begin(), mp.end(), pii(mp[i].first - m + 1, -INF));
      int pos = (it - mp.begin());
      sg.add(pos, i, i);
      // up
      it = lower_bound(mp.begin(), mp.end(), pii(mp[i].first + m, -INF));
      // it--;
      pos = (it - mp.begin());
      sg.add(i + 1, pos, i);
    }
    // cout << "setup finish" << endl;
    bool ret = sat.solve();
    // cout << "ret: " << ret << endl;
    return ret;
  };

  int l = 0, r = 1e9;
  while (r - l > 1) {
    int m = (l + r) / 2;
    if (fn(m)) {
      l = m;
    } else {
      r = m;
    }
  }

  cout << l << endl;

  return 0;
}