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: Time Limit Exceeded)

#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
template<class T>
inline void read(T &a){
    T s = 0, w = 1;
    char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') w = -1; c = getchar();}
    while(c >= '0' && c <= '9') {s = (s << 1) + (s << 3) + (c ^ 48); c = getchar();}
    a = s * w;
}
const int maxn = 643333;
int n, m, ans, tot, cnt;
int a[maxn], ans1[maxn];
int Block[maxn], Block_size;
struct Point{
    int x, y, pre, h;
}que[maxn], up[maxn];
int color[maxn];
inline void del(int x){
   // printf("%d\n", x);
    color[a[x]]--;
    if(color[a[x]] == 0) ans --;
}
inline void add(int x){
    color[a[x]]++;
    if(color[a[x]] == 1) ans ++;
}
int l, r, now;
inline void upadd(int now){
    int pos = up[now].x;
    if(l <= up[now].x && up[now].x <= r){
        color[a[pos]]--;
        if(color[a[pos]] == 0) ans--;
        color[up[now].y] ++;
        if(color[up[now].y] == 1) ans ++;
    }
    swap(a[pos], up[now].y);
}
inline void md(){
    l = 1,  r = 0;
    for (int i = 1; i <= tot; i++){
        while(l < que[i].x) del(l++);
        while(l > que[i].x) add(--l);
     //   printf("%d %d\n",l,r);
        while(r < que[i].y) add(++r);
        while(r > que[i].y) del(r--);
    //    while(now < que[i].pre) upadd(++now);
      //  while(now > que[i].pre) upadd(now--);
        ans1[que[i].h] = ans;
     //   printf("(%d, %d) (%d, %d)\n", que[i].x, que[i].y, l, r);
    }
    for (int i = 1; i <= tot; i++) printf("%d\n", ans1[i]);
}
int cmp(Point x, Point y){
    if(Block[x.x] != Block[y.x]) return Block[x.x] < Block[y.x];
    if(Block[x.y] != Block[y.y]) return Block[x.y] < Block[y.y];
    return x.pre < y.pre;
}
int t[maxn * 2], Helo;
int main(){
//	freopen("1.in","r", stdin);
	//freopen("1.out","w", stdout);
    read(n); read(m);
    Block_size = sqrt(n);
    for (int i = 1; i <= n; i++){
        read(a[i]);
		t[++Helo] = a[i];
        Block[i] = (i - 1) / Block_size + 1;
    }
    for (int i = 1; i <= m; i++){
        char c;
        int x, y;
        read(x); read(y);
        que[++tot].x = x; que[tot].y = y;
        que[tot].pre = cnt; que[tot].h = tot;
    }
	sort(t + 1, t + 1 + Helo);
    sort(que + 1, que + 1 + tot, cmp);
    md();
    return 0;
}