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

#pragma GCC optimize("Ofast", "unroll-loops")

#include <bits/stdc++.h>

using namespace std;

template <typename T> struct SegmentTree {
private:
  int sz, n;
  vector<T> data;
  function<T(T, T)> f;
  T identity_element;

public:
  /* constructor */
  SegmentTree(vector<T> v,        // initial data
              T identity_element, // identity element
              function<T(T, T)> f // operation
  ) {
    sz = v.size();
    n = 1;
    while (n < sz)
      n <<= 1;
    this->f = f;
    this->identity_element = identity_element;
    data.resize(2 * n - 1, identity_element);
    for (int i = 0; i < sz; ++i)
      data[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; --i)
      data[i] = f(data[2 * i + 1], data[2 * i + 2]);
  }
  /* update query */
  void update(int idx, const T val) {
    idx += n - 1;
    data[idx] = val;
    while (idx) {
      idx = (idx - 1) >> 1;
      data[idx] = f(data[2 * idx + 1], data[2 * idx + 2]);
    }
  }
  /* get query */
  T get(int left, int right, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (r <= left || right <= l)
      return identity_element;
    if (left <= l && r <= right)
      return data[k];
    T val_l = get(left, right, 2 * k + 1, l, (l + r) / 2);
    T val_r = get(left, right, 2 * k + 2, (l + r) / 2, r);
    return f(val_l, val_r);
  }
};

int main(void) {
  int N, Q;
  cin >> N >> Q;
  vector<int> c(N);
  for (auto &ci : c)
    cin >> ci;
  using q = tuple<int, int, int>;
  vector<q> que(Q);
  for (int i = 0; i < Q; ++i) {
    int l, r;
    cin >> l >> r;
    --l, --r;
    que[i] = make_tuple(l, r, i);
  }
  sort(que.begin(), que.end(),
       [](auto q1, auto q2) { return get<1>(q1) < get<1>(q2); });
  SegmentTree<int> seg(vector<int>(N + 1, 0), 0,
                       [](int a, int b) { return a + b; });
  vector<int> lastappered(N + 1, -1);
  int R = -1;
  vector<int> res(Q);
  for (int i = 0; i < Q; ++i) {
    int id = get<2>(que[i]);
    int l = get<0>(que[i]);
    int r = get<1>(que[i]);
    // cout << id << " " << l << " " << r << endl;
    while (R < r) {
      R++;
      int cr = c[R];
      int tmp = lastappered[cr];
      int t;
      if (tmp != -1) {
        t = seg.get(tmp, tmp + 1);
        seg.update(tmp, t - 1);
      }
      lastappered[cr] = R;
      t = seg.get(R, R + 1);
      seg.update(R, t + 1);
    }
    // for (int i = 0; i <= N; ++i)
    // 	cout << seg.get(i, i + 1) << " ";
    // cout << endl;
    res[id] = seg.get(l, r + 1);
  }
  for (auto r : res)
    cout << r << endl;
  return 0;
}

Error: TLE

Fixed submission:

#pragma GCC optimize("Ofast", "unroll-loops")

#include <bits/stdc++.h>

using namespace std;

int N, Q, width;
vector<int> c(1000000);

struct que {
  int id;   // クエリのid
  int l, r; // クエリの対象区間[l,r)
  que(int id, int l, int r) : id(id), l(l), r(r) {}
  que() : id(0), l(0), r(0) {}
};
vector<que> q(1000000);

void input(void) {
  (void)scanf("%d %d", &N, &Q);
  width = (int)sqrt(N) + 1;
  for (int i = 0; i < N; ++i)
    (void)scanf("%d ", &c[i]);
  for (int i = 0; i < Q; ++i) {
    int l, r;
    (void)scanf("%d %d", &l, &r);
    --l;
    q[i] = que(i, l, r);
  }
}

int ans = 0;
vector<int> cnt(1000000, 0);

vector<bool> v(1000000, false);

void build() {
  sort(q.begin(), q.begin() + Q, [&](que a, que b) {
    if (a.l / width != b.l / width)
      return a.l < b.l;
    return a.r < b.r;
  });
}
// data[idx]が区間に追加されるときの処理
void add(int idx) {
  if (cnt[c[idx]]++ == 0)
    ++ans;
}
// data[idx]が区間から削除されるときの処理
void del(int idx) {
  if (--cnt[c[idx]] == 0)
    --ans;
}
void distribute(int idx) {
  if (v[idx])
    del(idx);
  else
    add(idx);
  v[idx].flip();
}
// クエリを一つ処理する(処理したクエリのidが返される)
int process() {
  static int ptr = 0;
  static int nl = 0, nr = 0;
  if (ptr == Q)
    return -1;
  while (nl > q[ptr].l)
    distribute(--nl);
  while (nr < q[ptr].r)
    distribute(nr++);
  while (nl < q[ptr].l)
    distribute(nl++);
  while (nr > q[ptr].r)
    distribute(--nr);
  return (q[ptr++].id);
}

int main(void) {
  input();
  build();
  vector<int> res(1000000, 0);
  while (1) {
    int id = process();
    if (id == -1)
      break;
    res[id] = ans;
  }
  for (int i = 0; i < Q; ++i)
    printf("%d\\n", res[i]);
  return 0;
}