Problem p03709 (C++)

Buggy submission (status: Time Limit Exceeded):

#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.
 *
 * 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.
 * => To transform the problem by introducing the speed interval is the
 * => key to solve this problem!
 *
 * 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.
 * => Don't know how to do this, but come up w/ a nlog(n) alg. may be
 * => more general.
 */

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; }
} P[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 BIT[maxn];

/* incremental A[i] w/ value val */
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;
}

LL solve_bit() {
  memset(BIT, 0, sizeof(BIT));
  /* use BIT to count the number of paths in DAG */
  FOR(i, 1, N + 1) {
    const int src = I[1].a;
    const int lft = I[i].a;
    const int rht = I[i].b;
    /*
     * The 2 points does not have to be overlapping, they can be
     * next to each other, AB, not A. Hence lft-2.
     *                     ||      B
     */
    const LL val = query(BIT, N) - query(BIT, lft - 2);
    /* assert(val >= 0);   /\* this RE in test server?? *\/ */
    update(BIT, N + 10, rht, val + (lft == src));
  }
  const LL ans = (query(BIT, N) - query(BIT, N - 1) + mod) % mod;
  return ans;
}

LL dp[maxn];

LL dfs(const int i) {
  if (i == N)
    return 1;
  LL &ans = dp[i];
  if (ans == -1) {
    ans = (I[i].b == I[N].b);
    for (int j = i + 1; j <= N && I[i].b + 1 >= I[j].a; j++) {
      ans += dfs(j);
      ans %= mod;
    }
  }
  return ans;
}

LL solve_dp() {
  memset(dp, -1, sizeof(dp));
  LL ans = 0;
  FOR(i, 1, N + 1) if (I[i].a == I[1].a) {
    ans += dfs(i);
    ans %= mod;
  }
  return ans;
}

int main() {
  /* #ifndef ONLINE_JUDGE */
  /*     freopen("foo", "rt", stdin); */
  /* #endif */
  while (cin >> N) {
    FOR(i, 1, N + 1) {
      cin >> P[i].x >> P[i].v;
      V[i] = P[i].v;
    }
    sort(P + 1, P + N + 1);
    int maxx = 0;
    FOR(i, 1, N + 1) {
      maxx = max(maxx, P[i].v);
      R[i] = maxx;
    }
    int minn = inf;
    FORR(i, N, 0) {
      minn = min(minn, P[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[0],
                      lower_bound(V + 1, V + N + 1, R[i]) - &V[0]);
    }
    sort(I + 1, I + N + 1);
    /* const LL ans = solve_bit(); */
    const LL ans = solve_dp();
    cout << ans << endl;
  }
  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.
 *
 * 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.
 * => To transform the problem by introducing the speed interval is the
 * => key to solve this problem!
 *
 * 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.
 * => Don't know how to do this, but come up w/ a nlog(n) alg. may be
 * => more general.
 */

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; }
} P[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 BIT[maxn];

/* incremental A[i] w/ value val */
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;
}

LL solve_bit() {
  memset(BIT, 0, sizeof(BIT));
  /* use BIT to count the number of paths in DAG */
  FOR(i, 1, N + 1) {
    const int src = I[1].a;
    const int lft = I[i].a;
    const int rht = I[i].b;
    /*
     * The 2 points does not have to be overlapping, they can be
     * next to each other, AB, not A. Hence lft-2.
     *                     ||      B
     */
    const LL val = query(BIT, N) - query(BIT, lft - 2);
    /* assert(val >= 0);   /\* this RE in test server?? *\/ */
    update(BIT, N + 10, rht, val + (lft == src));
  }
  const LL ans = (query(BIT, N) - query(BIT, N - 1) + mod) % mod;
  return ans;
}

LL dp[maxn];

LL dfs(const int i) {
  if (i == N)
    return 1;
  LL &ans = dp[i];
  if (ans == -1) {
    ans = (I[i].b == I[N].b);
    for (int j = i + 1; j <= N && I[i].b + 1 >= I[j].a; j++) {
      ans += dfs(j);
      ans %= mod;
    }
  }
  return ans;
}

LL solve_dp() {
  memset(dp, -1, sizeof(dp));
  LL ans = 0;
  FOR(i, 1, N + 1) if (I[i].a == I[1].a) {
    ans += dfs(i);
    ans %= mod;
  }
  return ans;
}

int main() {
  /* #ifndef ONLINE_JUDGE */
  /*     freopen("foo", "rt", stdin); */
  /* #endif */
  while (cin >> N) {
    FOR(i, 1, N + 1) {
      cin >> P[i].x >> P[i].v;
      V[i] = P[i].v;
    }
    sort(P + 1, P + N + 1);
    int maxx = 0;
    FOR(i, 1, N + 1) {
      maxx = max(maxx, P[i].v);
      R[i] = maxx;
    }
    int minn = inf;
    FORR(i, N, 0) {
      minn = min(minn, P[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[0],
                      lower_bound(V + 1, V + N + 1, R[i]) - &V[0]);
    }
    sort(I + 1, I + N + 1);
    const LL ans = solve_bit();
    /* const LL ans = solve_dp(); */
    cout << ans << endl;
  }
  return 0;
}