Problem p03559 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define SZ(i) ((int)i.size())
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define get0(x) (get<0>(x))
#define get1(x) (get<1>(x))
#define get2(x) (get<2>(x))
#define ALL(X) (X).begin(), (X).end()
#define LLMAX 9223372036854775807LL
#define LLMIN -9223372036854775808LL
#define IMAX 2147483647
#define IMIN -2147483648
typedef long long LL;
using namespace std;

class RangeAddRangeSum {
public:
  int N;
  vector<int> dat, sum_dat;
  RangeAddRangeSum(int n) {
    N = 1;
    while (N < n)
      N <<= 1;
    dat.assign(2 * N - 1, 0);
    sum_dat.assign(2 * N - 1, 0);
  }

  void add(int a, int b, int x) { add(a, b, x, 0, 0, N); }
  int add(int a, int b, int x, int k, int l, int r) {
    if (b <= l or r <= a)
      return dat[k];
    if (a <= l and r <= b) {
      sum_dat[k] += x;
      return dat[k] += x * (r - l);
    }
    const int m = (l + r) / 2;
    return dat[k] = add(a, b, x, 2 * k + 1, l, m) +
                    add(a, b, x, 2 * k + 2, m, r) +
                    sum_dat[k] * (min(r, b) - max(l, a));
  }

  int sum(int a, int b) { return sum(a, b, 0, 0, N); }
  int sum(int a, int b, int k, int l, int r) {
    if (b <= l or r <= a)
      return 0;
    if (a <= l and r <= b)
      return dat[k];
    const int m = (l + r) / 2;
    return sum(a, b, 2 * k + 1, l, m) + sum(a, b, 2 * k + 2, m, r) +
           sum_dat[k] * (min(r, b) - max(l, a));
  }
};

int main(void) {
  int N;
  // cin>>N;
  scanf("%d", &N);
  vector<LL> ABC[3];
  REP(i, 3)
  REP(j, N) {
    LL x;
    // cin>>x;
    scanf("%lld", &x);
    ABC[i].pb(x);
    sort(ALL(ABC[i]));
  }
  LL ans = 0;
  // RangeAddRangeSum rsq(N);
  vector<LL> dat(N);
  REP(i, N) {
    // rsq.add(i,i+1,ABC[2].end()-upper_bound(ALL(ABC[2]),ABC[1][i]));
    dat[i] = ABC[2].end() - upper_bound(ALL(ABC[2]), ABC[1][i]);
  }
  LL sum = 0;
  LL index = N - 1;
  // REP(i,N){
  for (int i = N - 1; 0 <= i; i--) {
    // ans+=rsq.sum(upper_bound(ALL(ABC[1]),ABC[0][i])-ABC[1].begin(),N);
    int j = upper_bound(ALL(ABC[1]), ABC[0][i]) - ABC[1].begin();
    while (j <= index) {
      sum += dat[index];
      index--;
    }
    ans += sum;
  }
  cout << ans << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <limits.h>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define SZ(i) ((int)i.size())
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define get0(x) (get<0>(x))
#define get1(x) (get<1>(x))
#define get2(x) (get<2>(x))
#define ALL(X) (X).begin(), (X).end()
#define LLMAX 9223372036854775807LL
#define LLMIN -9223372036854775808LL
#define IMAX 2147483647
#define IMIN -2147483648
typedef long long LL;
using namespace std;

class RangeAddRangeSum {
public:
  int N;
  vector<int> dat, sum_dat;
  RangeAddRangeSum(int n) {
    N = 1;
    while (N < n)
      N <<= 1;
    dat.assign(2 * N - 1, 0);
    sum_dat.assign(2 * N - 1, 0);
  }

  void add(int a, int b, int x) { add(a, b, x, 0, 0, N); }
  int add(int a, int b, int x, int k, int l, int r) {
    if (b <= l or r <= a)
      return dat[k];
    if (a <= l and r <= b) {
      sum_dat[k] += x;
      return dat[k] += x * (r - l);
    }
    const int m = (l + r) / 2;
    return dat[k] = add(a, b, x, 2 * k + 1, l, m) +
                    add(a, b, x, 2 * k + 2, m, r) +
                    sum_dat[k] * (min(r, b) - max(l, a));
  }

  int sum(int a, int b) { return sum(a, b, 0, 0, N); }
  int sum(int a, int b, int k, int l, int r) {
    if (b <= l or r <= a)
      return 0;
    if (a <= l and r <= b)
      return dat[k];
    const int m = (l + r) / 2;
    return sum(a, b, 2 * k + 1, l, m) + sum(a, b, 2 * k + 2, m, r) +
           sum_dat[k] * (min(r, b) - max(l, a));
  }
};

int main(void) {
  int N;
  // cin>>N;
  scanf("%d", &N);
  vector<LL> ABC[3];
  REP(i, 3) {
    REP(j, N) {
      LL x;
      // cin>>x;
      scanf("%lld", &x);
      ABC[i].pb(x);
    }
    sort(ALL(ABC[i]));
  }
  LL ans = 0;
  // RangeAddRangeSum rsq(N);
  vector<LL> dat(N);
  REP(i, N) {
    // rsq.add(i,i+1,ABC[2].end()-upper_bound(ALL(ABC[2]),ABC[1][i]));
    dat[i] = ABC[2].end() - upper_bound(ALL(ABC[2]), ABC[1][i]);
  }
  LL sum = 0;
  LL index = N - 1;
  // REP(i,N){
  for (int i = N - 1; 0 <= i; i--) {
    // ans+=rsq.sum(upper_bound(ALL(ABC[1]),ABC[0][i])-ABC[1].begin(),N);
    int j = upper_bound(ALL(ABC[1]), ABC[0][i]) - ABC[1].begin();
    while (j <= index) {
      sum += dat[index];
      index--;
    }
    ans += sum;
  }
  cout << ans << endl;
  return 0;
}