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>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define pob pop_back
#define ff first
#define ss second
#define endl "\n"
#define all(a) a.begin(),a.end()
#define debug(x) cout << x << endl;
#define int long long
#define ordered_set tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
/* 	1) order_of_key (k) : Number of items strictly smaller than k .
	2) find_by_order(k) : K-th element in a set (counting from zero).
*/
using namespace __gnu_pbds;
using namespace std;
using LD = long double;

const int N = 5e5+1;
const int mod = 1e9+7;
const int INF = 1e18;
int row[8] = {1,1,0,-1,-1,-1,0,1};
int col[8] = {0,-1,-1,-1,0,1,1,1};

int n,q;
vector<int> segT(4*N);

bool cmp(pair<pair<int,int>,int>& A,pair<pair<int,int>,int>& B) {
	return A.ff.ss < B.ff.ss;
}

void update(int idx, int b, int e, int pos, int val) {
	if(b == e) {
		segT[idx] += val;
		return;
	}
	int mid = b+e>>1;
	if(pos <= mid)
		update(idx<<1,b,mid,pos,val);
	else
		update(idx<<1|1,mid+1,e,pos,val);
	segT[idx] = segT[idx<<1] + segT[idx<<1|1];
}

int query(int idx, int b, int e, int L, int R) {
	if(b > R or e < L)
		return 0;
	if(b >= L and e <= R)
		return segT[idx];
	int mid = b+e>>1;
	return query(idx<<1,b,mid,L,R) + query(idx<<1|1,mid+1,e,L,R);
}

void solve() {
	cin >> n >> q;
	vector<int> pos(n);
	
	for(int i=0;i<n;i++)
		cin >> pos[i];
		
	vector<pair<pair<int,int>,int>> vp(q);
	vector<int> ans(q);
	
	map<int,int> prev;
	
	for(int i=0;i<q;i++) {
		cin >> vp[i].ff.ff >> vp[i].ff.ss;
		vp[i].ff.ff--;
		vp[i].ff.ss--;
		vp[i].ss = i;
	}
	
	sort(all(vp),cmp);
	
	int j = 0;
	for(int i=0;i<n;i++) {
		
		if(prev.find(pos[i]) != prev.end()) {
			//cout << prev[pos[i]] << endl;
			update(1, 0, N-1, prev[pos[i]], -1);
		}
		
		update(1, 0, N-1, i, 1);
		
		while(j < q and vp[j].ff.ss == i) {
			ans[vp[j].ss] = query(1,0,N-1,vp[j].ff.ff,vp[j].ff.ss);
			j++;
		}
		
		prev[pos[i]] = i;
	}
	for(int i=0;i<q;i++)
		cout << ans[i] << endl;
}
 
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t = 1,i = 1;
    //cin >> t;
    while(t--) {
        //cout << "Case #" << i << ": ";
        solve();
        //i++;
    }
    return 0;
}