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

// AtCoder :: Beginner Contest 174 :: Range Set Query
// https://atcoder.jp/contests/abc174/tasks/abc174_f

#include <bits/stdc++.h>

using namespace std;

const int MAXN{500000};

// Ref: https://codeforces.com/blog/entry/61203
inline int64_t hilbertOrder(int x, int y, int pow, int rotate) {
  if (pow == 0) {
    return 0;
  }
  int hpow = 1 << (pow - 1);
  int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);
  seg = (seg + rotate) & 3;
  const int rotateDelta[4] = {3, 0, 0, 1};
  int nx = x & (x ^ hpow), ny = y & (y ^ hpow);
  int nrot = (rotate + rotateDelta[seg]) & 3;
  int64_t subSquareSize = int64_t(1) << (2 * pow - 2);
  int64_t ans = seg * subSquareSize;
  int64_t add = hilbertOrder(nx, ny, pow - 1, nrot);
  ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
  return ans;
}

struct Query {
  int left, right, index;
  int64_t ord;

  inline void calcOrder() { ord = hilbertOrder(left, right, 21, 0); }
};

inline bool operator<(const Query &lhs, const Query &rhs) {
  return lhs.ord < rhs.ord;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  int N, Q;
  cin >> N >> Q;
  vector<int> arr;
  arr.reserve(N);
  copy_n(istream_iterator<int>(cin), N, back_inserter(arr));
  vector<Query> queries(Q);
  for (int q{0}; q < Q; ++q) {
    cin >> queries[q].left >> queries[q].right;
    // Convert query to zero base
    queries[q].left--;
    queries[q].right--;
    queries[q].index = q;
    queries[q].calcOrder();
  }
  sort(queries.begin(), queries.end());
  vector<int> frequency(N + 1);
  vector<int> solns(queries.size());

  int currLeft{0};
  int currRight{-1};
  int distinctElems{0};
  for (auto query : queries) {
    while (currLeft < query.left) {
      // Remove element
      auto value = arr[currLeft];
      frequency[value]--;
      if (frequency[value] == 0) {
        distinctElems--;
      }
      currLeft++;
    }
    while (currLeft > query.left) {
      // Add element
      currLeft--;
      auto value = arr[currLeft];
      frequency[value]++;
      if (frequency[value] == 1) {
        distinctElems++;
      }
    }
    while (currRight < query.right) {
      // Add element
      currRight++;
      auto value = arr[currRight];
      frequency[value]++;
      if (frequency[value] == 1) {
        distinctElems++;
      }
    }
    while (currRight > query.right) {
      // Remove element
      auto value = arr[currRight];
      frequency[value]--;
      if (frequency[value] == 0) {
        distinctElems--;
      }
      currRight--;
    }
    solns[query.index] = distinctElems;
  }

  // Print results.
  copy(solns.begin(), solns.end(), ostream_iterator<int>(cout, "\\n"));
  return EXIT_SUCCESS;
}


Error: TLE

Fixed submission:

// AtCoder :: Beginner Contest 174 :: Range Set Query
// https://atcoder.jp/contests/abc174/tasks/abc174_f

#include <bits/stdc++.h>

using namespace std;

// Segment tree.
struct SegmentTree {
  vector<unordered_set<int>> st;
  int N;

  SegmentTree() {}

  SegmentTree(const vector<int> &arr) {
    N = static_cast<int>(arr.size());
    // Initialize segment tree twice the size of array.
    st = vector<unordered_set<int>>(2 * N);
    // Copy array values into segment tree nodes N ...
    for (int i{0}; i < arr.size(); ++i) {
      st[i + N].insert(arr[i]);
    }
    // Working up the tree, merge nodes.
    for (int i{N - 1}; i > 0; --i) {
      auto left = st[i << 1];
      auto right = st[i << 1 | 1];
      st[i].insert(left.begin(), left.end());
      st[i].insert(right.begin(), right.end());
    }
  }

  // Query on [left, right).  So add one if query is inclusive.
  int query(int left, int right) {
    unordered_set<int> result;
    for (left += N, right += N; left < right; left >>= 1, right >>= 1) {
      if (left & 1) {
        result.insert(st[left].begin(), st[left].end());
        left++;
      }
      if (right & 1) {
        --right;
        result.insert(st[right].begin(), st[right].end());
      }
    }
    return static_cast<int>(result.size());
  }
};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  int N, Q;
  cin >> N >> Q;
  vector<int> arr;
  arr.reserve(N + 1);
  arr.push_back(-1); // Convert to 1 based array with fill value.
  copy_n(istream_iterator<int>(cin), N, back_inserter(arr));
  SegmentTree st(arr);
  for (int q{0}; q < Q; ++q) {
    int left, right;
    cin >> left >> right;
    cout << st.query(left, right + 1) << "\\n";
  }
  return EXIT_SUCCESS;
}