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

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

// Macros
#define F first
#define S second
#define PB push_back

// Rename Datatypes
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

// Common Functions
ll fastpow(ll a, ll ex) {
  ll res = 1;
  while (ex) {
    if (ex & 1)
      res *= a;
    a *= a;
    ex >>= 1;
  }
  return res;
}
ll fastpow(ll a, ll ex, ll m) {
  a %= m;
  ll res = 1;
  while (ex) {
    if (ex & 1)
      res = (a * res) % m;
    a = (a * a) % m;
    ex >>= 1;
  }
  return res;
}
ll modinverse(ll a, ll m) {
  ll m0 = m, y = 0, x = 1;
  while (a > 1) {
    ll q = a / m;
    a %= m;
    swap(a, m);
    x -= q * y;
    swap(x, y);
  }
  if (x < 0)
    x += m0;
  return x;
}

// HELPERS
//  Tedious Grid Movements
vector<pii> moves_grid = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
inline bool move_okay(int x, int y, int n, int m) {
  return 0 <= x and x < n and 0 <= y and y < m;
}
//  Remember:
//   * vec.assign() GOOD; vec.resize() BAD
//   * comparator uses <

// CODE STARTS HERE

// 0-indexed
template <typename T> class FenwickTree {
private:
  const int n;
  vector<T> bits;

public:
  FenwickTree(int N) : n(N), bits(n + 1, 0) {}

  FenwickTree(vector<T> &arr) : FenwickTree(arr.size()) {
    for (int i = 0; i < n; ++i)
      add(i, arr[i]);
  }

  void add(int idx, T delta) {
    for (; idx <= n; idx += (idx & -idx))
      bits[idx] += delta;
  }

  T sum(int r) {
    T ret = 0;
    for (; r > 0; r -= (r & -r))
      ret += bits[r];
    return ret;
  }

  T sum(int l, int r) { return sum(r + 1) - sum(l); }
};

void solve() {
  int n, q;
  cin >> n >> q;

  vector<int> arr(n);
  for (auto &i : arr)
    cin >> i, --i;

  struct Query {
    int l, r, idx;
  };
  auto cmp = [](const auto lhs, const auto rhs) {
    if (lhs.r == rhs.r)
      return lhs.l < rhs.l;
    return lhs.r < rhs.r;
  };

  vector<Query> queries(q);
  for (int i = 0; i < q; ++i) {
    cin >> queries[i].l >> queries[i].r;
    --queries[i].l, --queries[i].r;
    queries[i].idx = i;
  }
  sort(queries.begin(), queries.end(), cmp);

  vector<int> ans(q);

  FenwickTree<int> fen{n};
  vector<int> last(n, -1);

  for (int i = 0, cnt = 0; i < n; ++i) {
    if (last[arr[i]] != -1)
      fen.add(last[arr[i]] + 1, -1);

    last[arr[i]] = i;
    fen.add(i + 1, 1);

    while (cnt < q and queries[cnt].r == i) {
      ans[queries[cnt].idx] = fen.sum(queries[cnt].l, queries[cnt].r);
      ++cnt;
    }
  }

  for (auto i : ans)
    cout << i << "\\n";
}

signed main(void) {
  // Fast_IO
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  // Set Fixed Notation (default sucks), High Precision for Floating-Point
  // Output
  cout << fixed << setprecision(20);

  // Multiple TCs
  int tt = 1;
  // cin >> tt;
  while (tt--)
    solve();
}


Error: TLE

Fixed submission:

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

// Macros
#define F first
#define S second
#define PB push_back

// Rename Datatypes
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

// Common Functions
ll fastpow(ll a, ll ex) {
  ll res = 1;
  while (ex) {
    if (ex & 1)
      res *= a;
    a *= a;
    ex >>= 1;
  }
  return res;
}
ll fastpow(ll a, ll ex, ll m) {
  a %= m;
  ll res = 1;
  while (ex) {
    if (ex & 1)
      res = (a * res) % m;
    a = (a * a) % m;
    ex >>= 1;
  }
  return res;
}
ll modinverse(ll a, ll m) {
  ll m0 = m, y = 0, x = 1;
  while (a > 1) {
    ll q = a / m;
    a %= m;
    swap(a, m);
    x -= q * y;
    swap(x, y);
  }
  if (x < 0)
    x += m0;
  return x;
}

// HELPERS
//  Tedious Grid Movements
vector<pii> moves_grid = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
inline bool move_okay(int x, int y, int n, int m) {
  return 0 <= x and x < n and 0 <= y and y < m;
}
//  Remember:
//   * vec.assign() GOOD; vec.resize() BAD
//   * comparator uses <

// CODE STARTS HERE

template <typename T, typename U = T> class SegmentTree {
protected:
  const int N;
  const T identity;
  const function<T(T, T)> combine;
  vector<T> segtree;

public:
  SegmentTree(const int n, const T idt, const function<T(T, T)> combine_)
      : N(n), identity(idt), combine(combine_), segtree(4 * N, identity) {}

  // FUTURE [C++20]: use std::identity for leaf
  SegmentTree(
      const int n, const T idt, const function<T(T, T)> combine_,
      const vector<U> &arr,
      const function<T(U)> leaf = [](U x) -> T { return x; })
      : SegmentTree(n, idt, combine_) {
    build(arr, leaf, 1, 0, N - 1);
  }

  /*Point*/ void update(int idx, T val) { update(idx, val, 1, 0, N - 1); }

  T query(int l, int r) { return query(l, r, 1, 0, N - 1); }

protected:
  void pull(int v) { segtree[v] = combine(segtree[2 * v], segtree[2 * v + 1]); }

  void build(const vector<U> &arr, const function<T(U)> &leaf, int v, int tl,
             int tr) {
    if (tl == tr) {
      segtree[v] = leaf(arr[tl]);
    } else {
      int tmid = (tl + tr) / 2;
      build(arr, leaf, 2 * v, tl, tmid);
      build(arr, leaf, 2 * v + 1, tmid + 1, tr);
      pull(v);
    }
  }

  /*Point*/
  void update(int idx, T val, int v, int tl, int tr) {
    if (tl == tr) {
      segtree[v] = val;
    } else {
      int tmid = (tl + tr) / 2;
      if (idx <= tmid)
        update(idx, val, 2 * v, tl, tmid);
      else
        update(idx, val, 2 * v + 1, tmid + 1, tr);
      pull(v);
    }
  }

  T query(int l, int r, int v, int tl, int tr) {
    if (tl > tr or tr < l or r < tl)
      return identity;

    if (l <= tl and tr <= r)
      return segtree[v];

    int tmid = (tl + tr) / 2;
    return combine(query(l, r, 2 * v, tl, tmid),
                   query(l, r, 2 * v + 1, tmid + 1, tr));
  }
};

void solve() {
  int n, q;
  cin >> n >> q;

  vector<int> arr(n);
  for (auto &i : arr)
    cin >> i;

  SegmentTree<vector<int>, int> segtree{
      n,
      {},
      [](auto lhs, auto rhs) -> vector<int> {
        vector<int> ret(lhs.size() + rhs.size());
        merge(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), ret.begin());
        ret.erase(unique(ret.begin(), ret.end()), ret.end());
        return ret;
      },
      arr,
      [](auto x) -> vector<int> { return {x}; }};

  while (q--) {
    int l, r;
    cin >> l >> r;
    --l, --r;
    cout << segtree.query(l, r).size() << "\\n";
  }
}

signed main(void) {
  // Fast_IO
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  // Set Fixed Notation (default sucks), High Precision for Floating-Point
  // Output
  cout << fixed << setprecision(20);

  // Multiple TCs
  int tt = 1;
  // cin >> tt;
  while (tt--)
    solve();
}