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

// C++ code to find number of distinct numbers
// in a subarray
#include <bits/stdc++.h>
using namespace std;

const int MAX = 1000001;

// structure to store queries
struct Query {
  int l, r, idx;
};

// cmp function to sort queries according to r
bool cmp(Query x, Query y) { return x.r < y.r; }

// updating the bit array
void update(int idx, int val, int bit[], int n) {
  for (; idx <= n; idx += idx & -idx)
    bit[idx] += val;
}

// querying the bit array
int query(int idx, int bit[], int n) {
  int sum = 0;
  for (; idx > 0; idx -= idx & -idx)
    sum += bit[idx];
  return sum;
}

void answeringQueries(int arr[], int n, Query queries[], int q) {
  // initialising bit array
  int bit[n + 1];
  memset(bit, 0, sizeof(bit));

  // holds the rightmost index of any number
  // as numbers of a[i] are less than or equal to 10^6
  int last_visit[MAX];
  memset(last_visit, -1, sizeof(last_visit));

  // answer for each query
  int ans[q];
  int query_counter = 0;
  for (int i = 0; i < n; i++) {
    // If last visit is not -1 update -1 at the
    // idx equal to last_visit[arr[i]]
    if (last_visit[arr[i]] != -1)
      update(last_visit[arr[i]] + 1, -1, bit, n);

    // Setting last_visit[arr[i]] as i and updating
    // the bit array accordingly
    last_visit[arr[i]] = i;
    update(i + 1, 1, bit, n);

    // If i is equal to r of any query store answer
    // for that query in ans[]
    while (query_counter < q && queries[query_counter].r == i) {
      ans[queries[query_counter].idx] =
          query(queries[query_counter].r + 1, bit, n) -
          query(queries[query_counter].l, bit, n);
      query_counter++;
    }
  }

  // print answer for each query
  for (int i = 0; i < q; i++)
    cout << ans[i] << endl;
}

// driver code
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);

  int n, q;
  cin >> n >> q;
  int a[n];
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  Query queries[q];
  for (int i = 0; i < q; i++) {
    int l, r;
    cin >> l >> r;
    queries[i].l = l - 1;
    queries[i].r = r - 1;
    queries[i].idx = i;
  }
  sort(queries, queries + q, cmp);
  answeringQueries(a, n, queries, q);
  return 0;
}


Error: TLE

Fixed submission:

#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")

#include <bits/stdc++.h>
using namespace std;

#define v vector
#define ALL(x) x.begin(), x.end()
#define rALL(x) x.rbegin(), x.rend()
#define endl '\\n'
#define F first
#define S second
#define DEBUG

template <typename T> void DBG(const char *name, T &&H) {
  cerr << name << " = " << H << ')' << endl;
}

template <typename T, typename... Args>
void DBG(const char *names, T &&H, Args &&...args) {
  const char *NEXT = strchr(names + 1, ',');
  cerr.write(names, NEXT - names) << " = " << H << " |";
  DBG(NEXT + 1, args...);
}

#ifdef DEBUG
#define dbg(...)                                                               \\
  cerr << __FUNCTION__ << ' ' << __LINE__ << " : (",                           \\
      DBG(#__VA_ARGS__, __VA_ARGS__)
#else
#define dbg(...)
#endif

using ll = long long;
using ld = long double;

const long long mod = 998244353;
const long double PI = acos(-1.0);
const long long INF = 1e18;
const int maxN = 2e5 + 1;

int blockSize;

template <typename S, typename T> struct Mo {
  S size, curL, curR;
  vector<T> arr;
  template <typename R> struct query {
    R l, r, idx;
    query(R x = 0, R y = 0, R id = 0) : l(x), r(y), idx(id) {}
    bool operator<(const query o) {
      if ((l / blockSize) != (o.l / blockSize))
        return ((l / blockSize) < (o.l / blockSize));
      else
        return (r < o.r);
    }
  };
  vector<T> ans;
  vector<query<S>> queries;
  // Variables or array to process your queries
  vector<T> colors;
  T curSum = 0;
  // finish
  Mo(S s) {
    size = s;
    blockSize = sqrt(s);
    arr.resize(s);
    colors.resize(s + 1, 0);
  }
  void addQuery(S l, S r, S idx) {
    ans.push_back(0);
    queries.push_back(query<S>(l, r, idx));
  }
  void add(S idx) {
    int val = arr[idx];
    if (colors[val] == 0) {
      curSum++;
    }
    colors[val]++;
  }
  void sub(S idx) {
    int val = arr[idx];
    if (colors[val] == 1) {
      curSum--;
    }
    colors[val]--;
  }
  T getAnswer() { return curSum; }
  void process() {
    sort(queries.begin(), queries.end());
    curL = 0, curR = -1;
    for (auto i : queries) {
      while (curL > i.l) {
        curL--;
        add(curL);
      }
      while (curR < i.r) {
        curR++;
        add(curR);
      }
      while (curL < i.l) {
        sub(curL);
        curL++;
      }
      while (curR > i.r) {
        sub(curR);
        curR--;
      }
      ans[i.idx] = getAnswer();
    }
  }
};

void Solve() {
  int N, Q;
  cin >> N >> Q;
  Mo<int, int> color(N);
  for (int i = 0; i < N; i++) {
    cin >> color.arr[i];
  }
  for (int i = 0; i < Q; i++) {
    int l, r;
    cin >> l >> r;
    l--;
    r--;
    color.addQuery(l, r, i);
  }
  color.process();
  for (int i = 0; i < Q; i++) {
    cout << color.ans[i] << endl;
  }
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);

  int tt = 1;
  while (tt--) {
    Solve();
  }

  return 0;
}