Problem p03709 (C++)

Buggy submission (status: Runtime Error):

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
// #include <regex>

/* g++ -g -std=c++0x */
/* g++ -g -std=c++11 */

using namespace std;

// std::ios::sync_with_stdio(false);

// freopen("input.txt", "rt", stdin);
// freopen("output.txt", "wt", stdout);

#define ALL(c) (c).begin(), (c).end()
#define ALLR(c) (c).rbegin(), (c).rend()
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define FORR(i, a, b) for (int i = (a); i > (b); --i)
#define FOR_ALL(i, c)                                                          \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define FOR_ALLR(i, c)                                                         \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); ++i)
#define SZ(array) (sizeof(array) / sizeof(array[0]))
#define lc(x) (x << 1)       /* 2*x */
#define rc(x) (x << 1 | 1)   /* 2*x+1 */
#define lowbit(x) (x & (-x)) /* 0b10100 -> 0b100 */

typedef long long LL;
typedef map<int, int> MII;
typedef pair<int, int> PII;
typedef set<int> SI;
typedef vector<bool> VB;
typedef vector<double> VD;
typedef vector<int> VI;
typedef vector<string> VS;

/* check if a key is in container C */
template <class C> inline bool in_(const typename C::key_type &k, const C &A) {
  return A.find(k) != A.end();
}
inline bool in_(const string &s, const string &S) {
  return S.find(s) != string::npos;
}

/*
 * Suppose that Xj < Xi and Vj > Vi. In this case, point j passes
 * through point i at some time, so point j becomes red. Suppose that
 * point k lies between i and j AFTER A SUFFICIENTLY LONG TIME
 * (i.e., Vi < Vk < Vj. It is easy to see that point k also becomes red.
 * => in the case of this speed arrangement, eventually we will have
 * => k in between i and j.
 *
 * Without loss of generality, we assume that the points are sorted in
 * the increasing order of V.
 * => this is just saying let's sort by V
 *
 * For each i, we define Ri as the maximum j such that Xj <= Xi. From
 * the observation above, all points between i and Ri will be red.
 * => for all point Xj <= Xi, find the max speed Ri
 *
 * Similarly, we define Li as the minimum j such that Xj >= Xi.
 * => for all point Xj >= Xi, find the min speed Li
 *
 * When we only choose point i at time 0, the set of red points after a
 * sufficiently long points will be the points between Li and Ri,
 * inclusive.
 * => very interesting property
 * => Any point with Li < speed < Ri (regardless its position), will
 * => become red.
 *
 * => Now we can use speed as range, instead of the position range,
 * => because the speed range is continuous, the position range is not.
 *
 * We can compute the arrays L and R in linear time. These arrays have
 * a special property: both L and R are monotonously increasing.
 *
 * We can restate the problem as follows:
 * You are given N intervals [L1,R1], .., [LN,RN], such that
 * L1 <= L2 <= ... and R1 <= R2 <= ...
 * Each interval is a subinterval of I. In how many ways can you choose
 * a subset of those N intervals such that the union of chosen intervals
 * becomes I?
 *
 * Construct a DAG with N+2 vertices. The vertices are numbered
 * 1 through N, and there are two special vertices S and T.
 *
 * When Li is the leftmost element of I, we add an edge from S to i.
 * When Ri is the rightmost element of I, we add an edge from i to T.
 * When i < j and Ri >= Lj - 1, we add an edge from i to j.
 *
 * The answer is the number of paths from S to T in this DAG. It can be
 * computed in O(N) DP and prefix sums.
 */

const int mod = 1e9 + 7;
const int inf = 1e9;
const int maxn = 1e6;

struct Point {
  int x, v;
  Point(const int x = 0, const int v = 0) : x(x), v(v) {}
  bool operator<(const Point &rhs) const { return x < rhs.x; }
} A[maxn];

struct Interval {
  int a, b;
  Interval(const int a = 0, const int b = 0) : a(a), b(b) {}
  bool operator<(const Interval &rhs) const {
    return PII(a, b) < PII(rhs.a, rhs.b);
  }
} I[maxn];

int N, L[maxn], R[maxn], V[maxn];
LL T[maxn];

void update(LL T[], const int n, int i, const LL val) {
  if (i > 0) {
    while (i < n) {
      T[i] += val;
      T[i] %= mod;
      i += (i & -i);
    }
  }
}

/* Query the *accumulative* value of A[1,i] */
LL query(const LL T[], int i) {
  LL sum = 0;
  if (i > 0) {
    while (i > 0) {
      sum += T[i];
      sum %= mod;
      i -= (i & -i);
    }
  }
  return sum;
}

int main() {
  /* #ifndef ONLINE_JUDGE */
  /*     freopen("foo", "rt", stdin); */
  /* #endif */
  while (cin >> N) {
    FOR(i, 1, N + 1) {
      cin >> A[i].x >> A[i].v;
      V[i] = A[i].v;
    }
    sort(A + 1, A + N + 1);
    int maxx = 0;
    FOR(i, 1, N + 1) {
      maxx = max(maxx, A[i].v);
      R[i] = maxx;
    }
    int minn = inf;
    FORR(i, N, 0) {
      minn = min(minn, A[i].v);
      L[i] = minn;
    }
    sort(V + 1, V + N + 1);
    FOR(i, 1, N + 1) {
      I[i] = Interval(/* get the index of V */
                      lower_bound(V + 1, V + N + 1, L[i]) - V,
                      lower_bound(V + 1, V + N + 1, R[i]) - V);
    }
    memset(T, 0, sizeof(T));
    sort(I + 1, I + N + 1);
    FOR(i, 1, N + 1) {
      const int src = I[1].a;
      const int lft = I[i].a;
      const int rht = I[i].b;
      const LL val = query(T, N) - query(T, lft - 2);
      assert(val >= 0);
      update(T, N + 10, rht, val + (lft == src));
    }
    const LL ans = (query(T, N) - query(T, N - 1) + mod) % mod;
    cout << ans << endl;
    break;
  }
  return 0;
}


Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
// #include <regex>

/* g++ -g -std=c++0x */
/* g++ -g -std=c++11 */

using namespace std;

// std::ios::sync_with_stdio(false);

// freopen("input.txt", "rt", stdin);
// freopen("output.txt", "wt", stdout);

#define ALL(c) (c).begin(), (c).end()
#define ALLR(c) (c).rbegin(), (c).rend()
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define FORR(i, a, b) for (int i = (a); i > (b); --i)
#define FOR_ALL(i, c)                                                          \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define FOR_ALLR(i, c)                                                         \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); ++i)
#define SZ(array) (sizeof(array) / sizeof(array[0]))
#define lc(x) (x << 1)       /* 2*x */
#define rc(x) (x << 1 | 1)   /* 2*x+1 */
#define lowbit(x) (x & (-x)) /* 0b10100 -> 0b100 */

typedef long long LL;
typedef map<int, int> MII;
typedef pair<int, int> PII;
typedef set<int> SI;
typedef vector<bool> VB;
typedef vector<double> VD;
typedef vector<int> VI;
typedef vector<string> VS;

/* check if a key is in container C */
template <class C> inline bool in_(const typename C::key_type &k, const C &A) {
  return A.find(k) != A.end();
}
inline bool in_(const string &s, const string &S) {
  return S.find(s) != string::npos;
}

/*
 * Suppose that Xj < Xi and Vj > Vi. In this case, point j passes
 * through point i at some time, so point j becomes red. Suppose that
 * point k lies between i and j AFTER A SUFFICIENTLY LONG TIME
 * (i.e., Vi < Vk < Vj. It is easy to see that point k also becomes red.
 * => in the case of this speed arrangement, eventually we will have
 * => k in between i and j.
 *
 * Without loss of generality, we assume that the points are sorted in
 * the increasing order of V.
 * => this is just saying let's sort by V
 *
 * For each i, we define Ri as the maximum j such that Xj <= Xi. From
 * the observation above, all points between i and Ri will be red.
 * => for all point Xj <= Xi, find the max speed Ri
 *
 * Similarly, we define Li as the minimum j such that Xj >= Xi.
 * => for all point Xj >= Xi, find the min speed Li
 *
 * When we only choose point i at time 0, the set of red points after a
 * sufficiently long points will be the points between Li and Ri,
 * inclusive.
 * => very interesting property
 * => Any point with Li < speed < Ri (regardless its position), will
 * => become red.
 *
 * => Now we can use speed as range, instead of the position range,
 * => because the speed range is continuous, the position range is not.
 *
 * We can compute the arrays L and R in linear time. These arrays have
 * a special property: both L and R are monotonously increasing.
 *
 * We can restate the problem as follows:
 * You are given N intervals [L1,R1], .., [LN,RN], such that
 * L1 <= L2 <= ... and R1 <= R2 <= ...
 * Each interval is a subinterval of I. In how many ways can you choose
 * a subset of those N intervals such that the union of chosen intervals
 * becomes I?
 *
 * Construct a DAG with N+2 vertices. The vertices are numbered
 * 1 through N, and there are two special vertices S and T.
 *
 * When Li is the leftmost element of I, we add an edge from S to i.
 * When Ri is the rightmost element of I, we add an edge from i to T.
 * When i < j and Ri >= Lj - 1, we add an edge from i to j.
 *
 * The answer is the number of paths from S to T in this DAG. It can be
 * computed in O(N) DP and prefix sums.
 */

const int mod = 1e9 + 7;
const int inf = 1e9;
const int maxn = 1e6;

struct Point {
  int x, v;
  Point(const int x = 0, const int v = 0) : x(x), v(v) {}
  bool operator<(const Point &rhs) const { return x < rhs.x; }
} A[maxn];

struct Interval {
  int a, b;
  Interval(const int a = 0, const int b = 0) : a(a), b(b) {}
  bool operator<(const Interval &rhs) const {
    return PII(a, b) < PII(rhs.a, rhs.b);
  }
} I[maxn];

int N, L[maxn], R[maxn], V[maxn];
LL T[maxn];

void update(LL T[], const int n, int i, const LL val) {
  if (i > 0) {
    while (i < n) {
      T[i] += val;
      T[i] %= mod;
      i += (i & -i);
    }
  }
}

/* Query the *accumulative* value of A[1,i] */
LL query(const LL T[], int i) {
  LL sum = 0;
  if (i > 0) {
    while (i > 0) {
      sum += T[i];
      sum %= mod;
      i -= (i & -i);
    }
  }
  return sum;
}

int main() {
  /* #ifndef ONLINE_JUDGE */
  /*     freopen("foo", "rt", stdin); */
  /* #endif */
  while (cin >> N) {
    FOR(i, 1, N + 1) {
      cin >> A[i].x >> A[i].v;
      V[i] = A[i].v;
    }
    sort(A + 1, A + N + 1);
    int maxx = 0;
    FOR(i, 1, N + 1) {
      maxx = max(maxx, A[i].v);
      R[i] = maxx;
    }
    int minn = inf;
    FORR(i, N, 0) {
      minn = min(minn, A[i].v);
      L[i] = minn;
    }
    sort(V + 1, V + N + 1);
    FOR(i, 1, N + 1) {
      I[i] = Interval(/* get the index of V */
                      lower_bound(V + 1, V + N + 1, L[i]) - V,
                      lower_bound(V + 1, V + N + 1, R[i]) - V);
    }
    memset(T, 0, sizeof(T));
    sort(I + 1, I + N + 1);
    FOR(i, 1, N + 1) {
      const int src = I[1].a;
      const int lft = I[i].a;
      const int rht = I[i].b;
      const LL val = query(T, N) - query(T, lft - 2);
      update(T, N + 10, rht, val + (lft == src));
    }
    const LL ans = (query(T, N) - query(T, N - 1) + mod) % mod;
    cout << ans << endl;
    break;
  }
  return 0;
}