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: Runtime Error)

// C++ implementation of above approach 
#include <bits/stdc++.h> 
using namespace std; 

// Each segment of the segment tree would be a set 
// to maintain distinct elements 
set<int>* segment; 

// Build the segment tree 
// i denotes current node, s denotes start and 
// e denotes the end of range for current node 
void build(int i, int s, int e, int arr[]) 
{ 

	// If start is equal to end then 
	// insert the array element 
	if (s == e) { 
		segment[i].insert(arr[s]); 
		return; 
	} 

	// Else divide the range into two halves 
	// (start to mid) and (mid+1 to end) 
	// first half will be the left node 
	// and the second half will be the right node 
	build(2 * i, s, (s + e) / 2, arr); 
	build(1 + 2 * i, 1 + (s + e) / 2, e, arr); 

	// Insert the sets of right and left 
	// node of the segment tree 
	segment[i].insert(segment[2 * i].begin(), 
					segment[2 * i].end()); 

	segment[i].insert(segment[2 * i + 1].begin(), 
					segment[2 * i + 1].end()); 
} 

// Query in an range a to b 
set<int> query(int node, int l, int r, int a, int b) 
{ 
	set<int> left, right, result; 

	// If the range is out of the bounds 
	// of this segment 
	if (b < l || a > r) 
		return result; 

	// If the range lies in this segment 
	if (a <= l && r <= b) 
		return segment[node]; 

	// Else query for the right and left 
	// leaf node of this subtree 
	// and insert them into the set 
	left = query(2 * node, l, (l + r) / 2, a, b); 
	result.insert(left.begin(), left.end()); 

	right = query(1 + 2 * node, 1 + (l + r) / 2, r, a, b); 
	result.insert(right.begin(), right.end()); 

	// Return the result 
	return result; 
} 

// Initialize the segment tree 
void init(int n) 
{ 
	// Get the height of the segment tree 
	int h = (int)ceil(log2(n)); 
	h = (2 * (pow(2, h))) - 1; 

	// Initialize the segment tree 
	segment = new set<int>[h]; 
} 

// Function to get the result for the 
// subarray from arr[l] to arr[r] 
void getDistinct(int l, int r, int n) 
{ 
	// Query for the range set 
	set<int> ans = query(1, 0, n - 1, l, r); 

	cout << ans.size() << endl; 
} 

// Driver code 
int main() 
{ 

	int i,j,n,q;
  	cin>>n>>q;
  	int arr[n];
  	for(i=0;i<n;i++) cin>>arr[i];
	//int n = sizeof(arr) / sizeof(arr[0]); 

	init(n); 

	// Bulid the segment tree 
	build(1, 0, n - 1, arr); 

	// Query in range 0 to 4 
	//getDistinct(0, 4, n);
  	while(q--)
    {
      int l,r;
      cin>>l>>r;
      l--;
      r--;
      getDistinct(l,r,n);
    }

	return 0; 
}