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

#include <bits/stdc++.h>

#ifdef DEBUG
#include <Mylib/Debug/debug.cpp>
#else
#define dump(...)
#endif

/**
 * @title Fenwick tree
 * @docs fenwick_tree.md
 */
template <typename AbelianGroup> class FenwickTree {
  using value_type = typename AbelianGroup::value_type;
  AbelianGroup G;

  int size;
  std::vector<value_type> data;

public:
  FenwickTree() {}
  FenwickTree(int size) : size(size), data(size + 1, G.id()) {}

  void update(int i, const value_type &val) {
    i += 1; // 1-index

    while (i <= size) {
      data[i] = G.op(data[i], val);
      i += i & (-i);
    }
  }

  value_type get(int i) const { // [0, i)
    value_type ret = G.id();
    i += 1; // 1-index

    while (i > 0) {
      ret = G.op(ret, data[i]);
      i -= i & (-i);
    }

    return ret;
  }

  value_type get(int l, int r) const { // [l, r)
    return G.op(get(r - 1), G.inv(get(l - 1)));
  }

  value_type at(int x) const { return get(x, x + 1); }
};

/**
 * @docs sum.md
 */
template <typename T> struct SumGroup {
  using value_type = T;

  value_type id() const { return 0; }
  value_type op(const value_type &a, const value_type &b) const {
    return a + b;
  }
  value_type inv(const value_type &a) const { return -a; }
};

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);

  int N, Q;

  while (std::cin >> N >> Q) {
    std::vector<int> c(N);
    for (int i = 0; i < N; ++i) {
      std::cin >> c[i];
      c[i] -= 1;
    }

    std::vector<std::pair<int, int>> query(Q);
    std::map<std::pair<int, int>, std::vector<int>> index;
    std::vector<int> ans(Q);

    for (int i = 0; i < Q; ++i) {
      int l, r;
      std::cin >> l >> r;
      --l;
      query[i] = std::make_pair(r, l);
      index[{l, r}].push_back(i);
    }

    FenwickTree<SumGroup<int>> b(N);
    std::vector<int> last_index(N, -1);

    std::sort(query.begin(), query.end());

    dump(query);

    int cur = 0;
    for (auto [r, l] : query) {
      while (cur < r) {
        if (last_index[c[cur]] != -1) {
          b.update(last_index[c[cur]], -1);
        }

        last_index[c[cur]] = cur;
        b.update(last_index[c[cur]], 1);

        ++cur;
      }

      for (auto i : index[{l, r}]) {
        ans[i] = b.get(l, r);
      }
    }

    for (auto x : ans) {
      std::cout << x << "\\n";
    }
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

/**
 * @title Mo's algorithm
 * @docs mo_algorithm.md
 */
template <typename F, typename G, typename H> class MoAlgorithm {
  int N, Q, index, width;
  std::vector<int> left, right, ord;

  const F append;
  const G remove;
  const H query;

  bool is_built = false;

public:
  MoAlgorithm(int N, int Q, const F &append, const G &remove, const H &query)
      : N(N), Q(Q), index(0), width(sqrt(N)), left(Q), right(Q), ord(Q),
        append(append), remove(remove), query(query) {}

  // [l, r)
  void add(int l, int r) {
    left[index] = l;
    right[index] = r;
    ord[index] = index;
    ++index;
  }

  void build() {
    std::sort(ord.begin(), ord.end(), [&](int i, int j) {
      const int a = left[i] / width, b = left[j] / width;
      if (a == b) {
        if (a & 1) {
          return right[i] < right[j];
        } else {
          return right[i] > right[j];
        }
      } else {
        return a < b;
      }
    });

    is_built = true;
  }

  void run() {
    assert(is_built);

    int q = 0;
    int l = left[ord[0]], r = left[ord[0]];

    for (int i = 0; i < Q; ++i) {
      int id = ord[q++];

      while (l != left[id] or r != right[id]) {
        if (l > left[id])
          append(--l);
        if (l < left[id])
          remove(l++);
        if (r < right[id])
          append(r++);
        if (r > right[id])
          remove(--r);
      }

      query(id);
    }
  }
};

template <typename F, typename G, typename H>
auto make_mo(int N, int Q, F append, G remove, H query) {
  return MoAlgorithm<F, G, H>(N, Q, append, remove, query);
}

int main() {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);

  int N, Q;

  while (std::cin >> N >> Q) {
    std::vector<int> c(N);
    for (int i = 0; i < N; ++i) {
      std::cin >> c[i];
      c[i] -= 1;
    }

    std::vector<int> count(N);
    int temp = 0;

    std::vector<int> ans(Q);

    auto append = [&](int i) {
      if (count[c[i]] == 0)
        ++temp;
      count[c[i]] += 1;
    };

    auto remove = [&](int i) {
      count[c[i]] -= 1;
      if (count[c[i]] == 0)
        --temp;
    };

    auto query = [&](int i) { ans[i] = temp; };

    auto mo = make_mo(N, Q, append, remove, query);

    for (int i = 0; i < Q; ++i) {
      int l, r;
      std::cin >> l >> r;
      mo.add(l - 1, r);
    }

    mo.build();
    mo.run();

    for (int i = 0; i < Q; ++i) {
      std::cout << ans[i] << "\\n";
    }
  }

  return 0;
}