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)

// #pragma GCC optimize ("O3")
// #pragma GCC target ("sse4")

#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 29;
const int NINF = -1*INF;
const long long LLINF = 1ll << 60;
const long long LLNINF = -1*LLINF;

template <class Ch, class Tr, class Container>
basic_ostream <Ch, Tr> & operator << (basic_ostream <Ch, Tr> & os, Container const& x) {
    os << "{ ";
    for(auto& y : x) os << y << " ";
    return os << "}";
}

template <class X, class Y>
ostream & operator << (ostream & os, pair <X, Y> const& p) {
	return os << "[ " << p.first << ", " << p.second << "]" ;
}

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
 
typedef pair<int, int> pi;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<ld> vld;
typedef vector<pi> vpi;
typedef vector<vector<int>> vvi;
typedef vector<vll> vvll;
typedef vector<vd> vvd;
typedef vector<vld> vvld;
 
#define mp make_pair
#define pb push_back
#define pf push_front
#define all(x) x.begin(), x.end()
#define revAll(x) x.rbegin(), x.rend()
#define gcd(a, b) __gcd(a, b)
#define popcount(x) __builtin_popcount(x)
#define isize(x) (int)(x.size())
#define rep(i,n) for(int i = 0; i < n; i++)
#define rep1(i, n) for(int i = 1; i < n+1; i++)
#define umap unordered_map

const ll MOD = 1e9 + 7;

struct SegTree{
	int n;
	vvi T;

	SegTree(vi& B){
		n = isize(B);
		T = vvi(4*n + 10);
		build(B, 1, 0, n-1);
	}

	void build(vi& B, int v, int tl, int tr){
		if (tl == tr){
			T[v] = {B[tl]};
		}else{
			int mid = (tl + tr)/2;
			build(B, 2*v, tl, mid);
			build(B, 2*v+1, mid+1, tr);
			vi new_v = vi();
			fcmerge(T[2*v], T[2*v+1], new_v);
			// merge(all(T[2*v]), all(T[2*v+1]), back_inserter(new_v));
			T[v] = new_v;
		}
	}

	void fcmerge(vi& A, vi& B, vi& res){
		int i = 0, j = 0, m = isize(A), n = isize(B);
		while (i < m and j < n){
			if (A[i] <= B[j]){
				res.pb(A[i]);
				i++;
			}else{
				res.pb(B[j]);
				j++;
			}			
		}
		if(i == m){
			while(j < n){
				res.pb(B[j]);
				j++;
			}
		}else{
			while(i < m){
				res.pb(A[i]);
				i++;
			}
		}
	}

	int qry(int l, int r, int x, int v, int tl, int tr){
		if (l > tr or r < tl) return 0;
		if (l <= tl and tr <= r){
			auto pt = lower_bound(all(T[v]), x+1);
			return distance(pt, T[v].end());
		}
		int mid = (tl + tr)/2;
		int L = qry(l, r, x, 2*v, tl, mid);
		int R = qry(l, r, x, 2*v+1, mid+1, tr);
		return L + R;
	}

};

int main(){
	ios_base::sync_with_stdio(false);cin.tie(0);
	int n, q; cin >> n >> q;
	vi A = vi();
	rep(i, n){
		int x; cin >> x;
		A.pb(x);
	}
	vi B = vi(n);
	umap<int, int> last = umap<int, int>();
	for(int i = isize(A)-1; i >= 0; i--){
		int val = A[i];
		if (last.find(val) == last.end()){
			B[i] = INF;
		}else{
			B[i] = last[val];
		}
		last[val] = i; 
	}
	SegTree ST = SegTree(B);
	rep(i, q){
		int l, r; cin >> l >> r;
		l--, r--;
		int ans = ST.qry(l, r, r, 1, 0, isize(B)-1);
		cout << ans << "\n";
	}
}