Problem p02599 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <ciso646>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop                                                                   \
  char nyaa;                                                                   \
  cin >> nyaa;
#define rep(i, n) for (int i = 0; i < n; i++)
#define per(i, n) for (int i = n - 1; i >= 0; i--)
#define Rep(i, sta, n) for (int i = sta; i < n; i++)
#define Per(i, sta, n) for (int i = n - 1; i >= sta; i--)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define per1(i, n) for (int i = n; i >= 1; i--)
#define Rep1(i, sta, n) for (int i = sta; i <= n; i++)
typedef long double ld;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

struct Mo {
  using F = function<void(int)>;
  vector<int> ls, rs, ord;
  int n, width, nl, nr, ptr; // widthは分割するバレットの幅
  F expandL, expandR;
  F shrinkL, shrinkR;

  Mo(int n, int width, F expandL, F expandR, F shrinkL, F shrinkR)
      : n(n), width(width), nl(0), nr(0), ptr(0), expandL(expandL),
        expandR(expandR), shrinkL(shrinkL), shrinkR(shrinkR) {}

  Mo(int n, int width, F expand, F shrink) {
    *this = Mo(n, width, expand, expand, shrink, shrink);
  }

  void add(int l, int r) { // 区間[l,r)
    ls.emplace_back(l);
    rs.emplace_back(r);
  }

  void build() {
    ord.resize(ls.size());
    iota(ord.begin(), ord.end(), 0);
    sort(ord.begin(), ord.end(), [&](int a, int b) {
      if (ls[a] / width != ls[b] / width)
        return ls[a] < ls[b];
      if (rs[a] == rs[b])
        return ls[a] < ls[b];
      return bool((rs[a] < rs[b]) ^ ((ls[a] / width) & 1));
    });
  }

  int process() {
    if (ptr == (int)ord.size())
      return -1;
    const int idx = ord[ptr++];
    while (nl > ls[idx])
      expandL(--nl);
    while (nr < rs[idx])
      expandR(nr++);
    while (nl < ls[idx])
      shrinkL(nl++);
    while (nr > rs[idx])
      shrinkR(--nr);
    return idx;
  }
};

void solve() {
  int n, q;
  cin >> n >> q;
  vector<int> c(n), cnt(n), ans(q);
  rep(i, n) {
    cin >> c[i];
    c[i]--;
  }
  int num = 0;
  auto expand = [&](int k) {
    cnt[c[k]] += 1;
    if (cnt[c[k]] == 1)
      num += 1;
  };
  auto shrink = [&](int k) {
    cnt[c[k]] -= 1;
    if (cnt[c[k]] == 0)
      num -= 1;
  };
  Mo mo(n, 1000, expand, shrink);
  rep(i, q) {
    int l, r;
    cin >> l >> r;
    l--;
    mo.add(l, r);
  }
  mo.build();
  rep(i, q) {
    int k = mo.process();
    ans[k] = num;
  }
  rep(i, q) { cout << ans[i] << "\n"; }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(50);
  solve();
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <ciso646>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop                                                                   \
  char nyaa;                                                                   \
  cin >> nyaa;
#define rep(i, n) for (int i = 0; i < n; i++)
#define per(i, n) for (int i = n - 1; i >= 0; i--)
#define Rep(i, sta, n) for (int i = sta; i < n; i++)
#define Per(i, sta, n) for (int i = n - 1; i >= sta; i--)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define per1(i, n) for (int i = n; i >= 1; i--)
#define Rep1(i, sta, n) for (int i = sta; i <= n; i++)
typedef long double ld;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

struct Mo {
  using F = function<void(int)>;
  vector<int> ls, rs, ord;
  int n, width, nl, nr, ptr; // widthは分割するバレットの幅
  F expandL, expandR;
  F shrinkL, shrinkR;

  Mo(int n, int width, F expandL, F expandR, F shrinkL, F shrinkR)
      : n(n), width(width), nl(0), nr(0), ptr(0), expandL(expandL),
        expandR(expandR), shrinkL(shrinkL), shrinkR(shrinkR) {}

  Mo(int n, int width, F expand, F shrink) {
    *this = Mo(n, width, expand, expand, shrink, shrink);
  }

  void add(int l, int r) { // 区間[l,r)
    ls.emplace_back(l);
    rs.emplace_back(r);
  }

  void build() {
    ord.resize(ls.size());
    iota(ord.begin(), ord.end(), 0);
    sort(ord.begin(), ord.end(), [&](int a, int b) {
      if (ls[a] / width != ls[b] / width)
        return ls[a] < ls[b];
      if (rs[a] == rs[b])
        return ls[a] < ls[b];
      return bool((rs[a] < rs[b]) ^ ((ls[a] / width) & 1));
    });
  }

  int process() {
    if (ptr == (int)ord.size())
      return -1;
    const int idx = ord[ptr++];
    while (nl > ls[idx])
      expandL(--nl);
    while (nr < rs[idx])
      expandR(nr++);
    while (nl < ls[idx])
      shrinkL(nl++);
    while (nr > rs[idx])
      shrinkR(--nr);
    return idx;
  }
};

void solve() {
  int n, q;
  cin >> n >> q;
  vector<int> c(n), cnt(n), ans(q);
  rep(i, n) {
    cin >> c[i];
    c[i]--;
  }
  int num = 0;
  auto expand = [&](int k) { num += cnt[c[k]]++ == 0; };
  auto shrink = [&](int k) { num -= --cnt[c[k]] == 0; };
  Mo mo(n, 1000, expand, shrink);
  rep(i, q) {
    int l, r;
    cin >> l >> r;
    l--;
    mo.add(l, r);
  }
  mo.build();
  rep(i, q) {
    int k = mo.process();
    ans[k] = num;
  }
  rep(i, q) { cout << ans[i] << "\n"; }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(50);
  solve();
}