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

#include <bits/stdc++.h>
#define INF 1e9
using namespace std;

#define REPR(i, n) for (int i = (n); i >= 0; --i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define ALL(a) (a).begin(), (a).end()
#define endl "\\n"

template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
typedef long long ll;

// 1-indexed
template <typename T> class BIT {
private:
  vector<T> arr;
  const int n;

public:
  BIT(int _n) : arr(_n + 1, 0), n(_n) {}

  T sum(int i) {
    T s = 0;
    while (i > 0) {
      s += arr[i];
      i -= i & -i; // LSB 減算
    }
    return s;
  }

  T sum(int i, int j) {
    auto ri = sum(i - 1);
    auto rj = sum(j);
    return rj - ri;
  }
  // 要素の加減算
  void add(int i, T x) {
    while (i <= n) {
      arr[i] += x;
      i += i & -i;
    }
  }

  void print() {
    for (const auto &it : arr) {
      cerr << it << endl;
    }
  }
};

void solve() {
  int N, Q;
  cin >> N >> Q;

  vector<int> v(N);
  REP(i, N) cin >> v[i];

  BIT<int> b(N);
  // r,l,id
  vector<tuple<int, int, int>> vt(Q);
  REP(i, Q) {
    int l, r;
    cin >> l >> r;
    vt[i] = make_tuple(r, l, i);
  }

  sort(ALL(vt));
  vector<int> ans(Q);
  // ballの種類とその場所(v依存、0-indexed)
  map<int, int> m;
  int state = 0; // 最後に作成した場所
  for (const auto tp : vt) {
    auto [r, l, id] = tp;
    FOR(i, state + 1, r + 1) {
      int val = v[i - 1];
      if (m.count(val)) {
        b.add(m[val] + 1, -1);
      }
      m[val] = i - 1;
      // update
      b.add(i, 1);
    }
    state = r;
    ans[id] = b.sum(l, r);
  }

  for (const auto &a : ans)
    cout << a << endl;
}

int main() {
  solve();
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define INF 1e9
using namespace std;

#define REPR(i, n) for (int i = (n); i >= 0; --i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define ALL(a) (a).begin(), (a).end()
#define endl "\\n"

template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
typedef long long ll;

class SegmentTree {
  int _sz;
  vector<set<int>> v;
  ll near_pow(ll sz) {
    ll k = 1;
    while (sz > k)
      k *= 2;
    return k;
  }

public:
  SegmentTree(int sz) {
    _sz = near_pow(sz);
    v.resize((2 * _sz) - 1, set<int>());
    REP(i, sz) {
      int c;
      cin >> c;
      v[_sz - 1 + i].insert(c);
    }
    FOR(i, sz, _sz) v[_sz - 1 + i] = v[_sz + sz - 2]; // 残りを最後の要素で埋める
    // 葉以外の要素を求める。
    REPR(i, _sz - 2)
    set_union(begin(v[(2 * i) + 1]), end(v[(2 * i) + 1]), begin(v[(2 * i) + 2]),
              end(v[(2 * i) + 2]), inserter(v[i], end(v[i])));
  }
  void print() {
    REP(i, v.size()) {
      cerr << "------------" << i << "-------------" << endl;
      for (const auto &it : v[i])
        cout << it << ", ";
      cout << endl;
    }
  }

  // 区間[a,b)の要素数を求める。
  // [l,r)は自分の今いるノードの区間、kは自分の今いるノードのインデックス。
  set<int> get(int a, int b, int l = 0, int r = -1, int k = 0) {
    // 初期化処理 最初は[l,r) = [0,N)
    if (r < 0)
      r = _sz;

    // if(a==b) return v[_sz-1+a];

    // 欲しい区間と今いるノードの区間が交わらないなら答えに影響のない値を適当に返す
    if (l >= b || r <= a)
      return set<int>();

    // 今いるノードの区間が全て欲しい区間の中だったらそれを答えに使う
    if (a <= l && r <= b)
      return v[k];

    // 今いるノードの区間の一部が欲しい場合は探索を進める。
    // 自分の今いるノードの区間を半分に分けて探索する。
    auto vl = get(a, b, l, (l + r) / 2, 2 * k + 1);
    auto vr = get(a, b, (l + r) / 2, r, 2 * k + 2);

    set<int> res;

    set_union(begin(vl), end(vl), begin(vr), end(vr), inserter(res, end(res)));

    return res;
  }
};

void solve() {
  int N, Q;
  cin >> N >> Q;
  SegmentTree s(N);
  REP(_, Q) {
    int l, r;
    cin >> l >> r;
    l--;
    auto ret = s.get(l, r);
    cout << ret.size() << endl;
  }
}

int main() {
  solve();
  return 0;
}