Problem p02599 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define loop(__x, __start, __end) for (int __x = __start; __x < __end; __x++)

typedef pair<int, int> P;
int N;
vector<int> A;
const int MONOID = 0;
ll f(ll x, ll y) { return x + y; }

void add(ll x, ll y) {
  ll i = x + N - 1;
  A.at(i) += y;
  while (i > 0) {
    i = (i - 1) / 2;
    A.at(i) = f(A.at(i * 2 + 1), A.at(i * 2 + 2));
  }
}

ll findRec(ll x, ll y, ll n, ll l, ll r) {
  if (r <= x || y <= l)
    return MONOID;
  if (x <= l && r <= y)
    return A.at(n);
  return f(findRec(x, y, n * 2 + 1, l, (l + r) / 2),
           findRec(x, y, n * 2 + 2, (l + r) / 2, r));
}

ll find(ll x, ll y) { return findRec(x, y + 1, 0, 0, N); }

int main() {
  int n, q;
  cin >> n >> q;
  N = 1;
  while (N < n)
    N *= 2;
  vector<int> C(n);
  A.assign(3 * n, 0);
  loop(i, 0, n) cin >> C[i];

  vector<int> points[n + 1];
  vector<int> prev(n + 1, -1);
  loop(i, 0, n) {
    int c = C[i];
    if (prev[c] != -1) {
      points[prev[c]].emplace_back(i);
    }
    prev[c] = i;
  }

  vector<P> qs[n + 1];
  loop(i, 0, q) {
    int l, r;
    cin >> l >> r;
    l--;
    r--;
    qs[l].emplace_back(r, i);
  }

  vector<int> ans(q, 0);
  for (int x = n - 1; x >= 0; x--) {
    for (auto &&y : points[x]) {
      add(y, 1);
    }
    for (auto q : qs[x]) {
      ans[q.second] = q.first - x + 1 - find(0, q.first);
    }
  }
  loop(i, 0, q) cout << ans[i] << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define loop(__x, __start, __end) for (int __x = __start; __x < __end; __x++)

#define K 2
struct Point {
  int coords[K];
  int id;
};

class KDTree {
public:
  int dimension;
  vector<Point> points;

  KDTree(vector<Point> points, int dimension) {
    this->points = points;
    this->dimension = dimension;

    buildkDTree();
  }

  void searchRange(Point start, Point end, vector<int> &result) {
    searchRangeRec(start, end, result, 0, points.size() - 1, 0);
  }

private:
  void buildkDTree() { buildTreeRec(0, points.size() - 1, 0); }

  bool asc(Point p1, Point p2, int d) { return p1.coords[d] < p2.coords[d]; }

  void buildTreeRec(int left, int right, int depth) {
    if (right < left)
      return;

    int cd = depth % dimension; // current dimension
    auto dAsc = [cd, this](Point p1, Point p2) { return asc(p1, p2, cd); };
    sort(points.begin() + left, points.begin() + right + 1, dAsc);

    int mid = (left + right) / 2;
    buildTreeRec(left, mid - 1, depth + 1);
    buildTreeRec(mid + 1, right, depth + 1);
  }

  int checkIncluded(Point point, Point start, Point end, int dimension) {
    if (start.coords[dimension] <= point.coords[dimension] &&
        point.coords[dimension] <= end.coords[dimension]) {
      return 0;
    }

    if (point.coords[dimension] < start.coords[dimension])
      return -1;
    return 1;
  }

  void searchRangeRec(Point start, Point end, vector<int> &result, int left,
                      int right, int depth) {
    if (right < left)
      return;
    int cd = depth % dimension; // current dimension
    int mid = (left + right) / 2;
    bool inArea = true;
    loop(i, 0, dimension) inArea &=
        checkIncluded(points[mid], start, end, i) == 0;
    if (inArea)
      result.push_back(points[mid].id);
    if (right == left)
      return;
    int included = checkIncluded(points[mid], start, end, cd);
    if (included == 0) {
      searchRangeRec(start, end, result, left, mid - 1, depth + 1);
      searchRangeRec(start, end, result, mid + 1, right, depth + 1);
    } else if (included == -1) {
      searchRangeRec(start, end, result, mid + 1, right, depth + 1);
    } else if (included == 1) {
      searchRangeRec(start, end, result, left, mid - 1, depth + 1);
    }
  }
};

int main() {
  int n, q;
  cin >> n >> q;
  vector<int> C(n);
  loop(i, 0, n) cin >> C[i];

  vector<Point> points;
  vector<int> prev(500001, -1);
  loop(i, 0, n) {
    int c = C[i];
    if (prev[c] != -1) {
      Point p;
      p.coords[0] = prev[c];
      p.coords[1] = i;
      p.id = points.size();
      points.push_back(p);
    }
    prev[c] = i;
  }

  KDTree kdTree(points, 2);

  loop(i, 0, q) {
    int l, r;
    cin >> l >> r;
    l--;
    r--;
    Point start;
    start.coords[0] = l;
    start.coords[1] = -600000;
    Point end;
    end.coords[0] = 600000;
    end.coords[1] = r;
    int ans = r - l + 1;
    vector<int> result;
    kdTree.searchRange(start, end, result);
    ans -= result.size();
    cout << ans << endl;
  }
  return 0;
}