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;

inline int64_t hilbertOrder(int x, int y, int pow, int rotate) {
	if (pow == 0) {
		return 0;
	}
	int hpow = 1 << (pow-1);
	int seg = (x < hpow) ? (
		(y < hpow) ? 0 : 3
	) : (
		(y < hpow) ? 1 : 2
	);
	seg = (seg + rotate) & 3;
	const int rotateDelta[4] = {3, 0, 0, 1};
	int nx = x & (x ^ hpow), ny = y & (y ^ hpow);
	int nrot = (rotate + rotateDelta[seg]) & 3;
	int64_t subSquareSize = int64_t(1) << (2*pow - 2);
	int64_t ans = seg * subSquareSize;
	int64_t add = hilbertOrder(nx, ny, pow-1, nrot);
	ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
	return ans;
}



const int N = 5e5+7, RT = 800;
int cnt[N], a[N], out[N], l[N], r[N];
long long ord[N];
int ans = 0;

void add(int x) {
    if (cnt[x] == 0)    ans++;
    cnt[x]++;
}

void rem(int x) {
    cnt[x]--;
    if (cnt[x] == 0)    ans--;
}


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

    int n, q;
    cin>>n>>q;

    for (int i=1; i<=n; i++)    cin>>a[i];

    vector<int> qq;
    for (int i=1; i<=q; i++) {
        cin>>l[i]>>r[i];
        qq.push_back(i);
        ord[i] = hilbertOrder(l[i], r[i], 20, 0);
    }

    sort(qq.begin(), qq.end(), [](auto a, auto b) {return ord[a] < ord[b];});

    int cl = 1, cr = 0;

    for (int id: qq) {
        while (cr < r[id])  add(a[++cr]);
        while (cl > l[id])  add(a[--cl]);
        while (cr > r[id])  rem(a[cr--]);
        while (cl < l[id])  rem(a[cl++]);

        out[id] = ans;
    }

    for (int i=1; i<=q; i++)    cout<<out[i]<<"\n";
}