Problem:
Score : 600 points

Problem Statement

We have N colored balls arranged in a row from left to right; the color of the i-th ball from the left is c_i.

You are given Q queries. The i-th query is as follows: how many different colors do the l_i-th through r_i-th balls from the left have?

Constraints

1\leq N,Q \leq 5 \times 10^5

1\leq c_i \leq N

1\leq l_i \leq r_i \leq N

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
c_1 c_2 \cdots c_N
l_1 r_1
l_2 r_2
:
l_Q r_Q

Output

Print Q lines. The i-th line should contain the response to the i-th query.

Sample Input 1

4 3
1 2 1 3
1 3
2 4
3 3

Sample Output 1

2
3
1

The 1-st, 2-nd, and 3-rd balls from the left have the colors 1, 2, and 1 - two different colors.

The 2-st, 3-rd, and 4-th balls from the left have the colors 2, 1, and 3 - three different colors.

The 3-rd ball from the left has the color 1 - just one color.

Sample Input 2

10 10
2 5 6 5 2 1 7 9 7 2
5 5
2 4
6 7
2 2
7 8
7 9
1 8
6 9
8 10
6 8

Sample Output 2

1
2
2
1
2
2
6
3
3
3

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

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

#ifdef LOCAL
#include "debug.h"
#else
#define DEBUG(...)
#endif

struct mo_t {
  int n;
  vector<pair<int, int>> lr;
  mo_t(int _n) : n(_n) {}
  void add(int l, int r) { lr.emplace_back(l, r); }
  template <class AL, class AR, class RL, class RR, class O>
  void run(AL add_left, AR add_right, RL remove_left, RR remove_right, O out) {
    int q = size(lr), bs = n / clamp<int>(sqrt(q * 2 / 3), 1, n);
    vector<int> ord(q);
    iota(begin(ord), end(ord), 0);
    sort(begin(ord), end(ord), [&](int i, int j) {
      auto [li, ri] = lr[i];
      auto [lj, rj] = lr[j];
      li /= bs, lj /= bs;
      return li != lj ? li < lj : li & 1 ? ri > rj : ri < rj;
    });
    int l = 0, r = 0;
    for (int i : ord) {
      auto [li, ri] = lr[i];
      while (l > li) add_left(--l);
      while (r < ri) add_right(r++);
      while (l < li) remove_left(l++);
      while (r > ri) remove_right(--r);
      out(i);
    }
  }
};

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  int n, q;
  cin >> n >> q;
  vector<int> c(n);
  for (auto&& e : c) cin >> e, --e;
  mo_t mo(n);
  vector<int> res(q), cnt(n);
  int cur = 0;
  auto add = [&](int i) {
    cur += cnt[c[i]]++ == 0;
  };
  auto remove = [&](int i) {
    cur -= --cnt[c[i]] == 0;
  };
  auto out = [&](int id) {
    res[id] = cur;
  };
  while (q--) {
    int l, r;
    cin >> l >> r;
    --l;
    mo.add(l, r);
  }
  mo.run(add, add, remove, remove, out);
  for (int e : res) {
    cout << e << '\n';
  }
}