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)

// Program to compute no. of different elements 
// of ranges for different range queries 
#include <bits/stdc++.h> 
using namespace std; 

// Used in frequency array (maximum value of an 
// array element). 
const int MAX = 1000000; 

// Variable to represent block size. This is made 
// global so compare() of sort can use it. 
int block; 

// Structure to represent a query range and to store 
// index and result of a particular query range 
struct Query { 
   int L, R, index, result; 
}; 

// Function used to sort all queries so that all queries 
// of same block are arranged together and within a block, 
// queries are sorted in increasing order of R values. 
bool compare(Query x, Query y) 
{ 
   // Different blocks, sort by block. 
   if (x.L / block != y.L / block) 
      return x.L / block < y.L / block; 

   // Same block, sort by R value 
   return x.R < y.R; 
} 

// Function used to sort all queries in order of their 
// index value so that results of queries can be printed 
// in same order as of input 
bool compare1(Query x, Query y) 
{ 
   return x.index < y.index; 
} 

// calculate distinct elements of all query ranges. 
// m is number of queries n is size of array a[]. 
void queryResults(int a[], int n, Query q[], int m) 
{ 
   // Find block size 
   block = (int)sqrt(n); 

   // Sort all queries so that queries of same 
   // blocks are arranged together. 
   sort(q, q + m, compare); 

   // Initialize current L, current R and current 
   // different elements 
   int currL = 0, currR = 0; 
   int curr_Diff_elements = 0; 

   // Initialize frequency array with 0 
   int freq[MAX] = { 0 }; 

   // Traverse through all queries 
   for (int i = 0; i < m; i++) { 
      
      // L and R values of current range 
      int L = q[i].L, R = q[i].R; 

      // Remove extra elements of previous range. 
      // For example if previous range is [0, 3] 
      // and current range is [2, 5], then a[0] 
      // and a[1] are subtracted 
      while (currL < L) { 
         
         // element a[currL] is removed 
         freq[a[currL]]--; 
         if (freq[a[currL]] == 0) 
            curr_Diff_elements--; 
         
         currL++; 
      } 

      // Add Elements of current Range 
      // Note:- during addition of the left 
      // side elements we have to add currL-1 
      // because currL is already in range 
      while (currL > L) { 
         freq[a[currL - 1]]++; 

         // include a element if it occurs first time 
         if (freq[a[currL - 1]] == 1) 
            curr_Diff_elements++; 
         
         currL--; 
      } 
      while (currR <= R) { 
         freq[a[currR]]++; 

         // include a element if it occurs first time 
         if (freq[a[currR]] == 1) 
            curr_Diff_elements++; 
         
         currR++; 
      } 

      // Remove elements of previous range. For example 
      // when previous range is [0, 10] and current range 
      // is [3, 8], then a[9] and a[10] are subtracted 
      // Note:- Basically for a previous query L to R 
      // currL is L and currR is R+1. So during removal 
      // of currR remove currR-1 because currR was 
      // never included 
      while (currR > R + 1) { 

         // element a[currL] is removed 
         freq[a[currR - 1]]--; 

         // if occurrence of a number is reduced 
         // to zero remove it from list of 
         // different elements 
         if (freq[a[currR - 1]] == 0) 
            curr_Diff_elements--; 
         
         currR--; 
      } 
      q[i].result = curr_Diff_elements; 
   } 
} 

// print the result of all range queries in 
// initial order of queries 
void printResults(Query q[], int m) 
{ 
   sort(q, q + m, compare1); 
   for (int i = 0; i < m; i++) { 
      cout << q[i].result << endl; 
   } 
} 

// Driver program 
int main() 
{ 
   int n,m;
   cin >> n >> m;
   int a[n];
   for(int i = 0; i < n; ++i){
      cin >> a[i];
   }
   Query q[m];
   for(int i = 0; i < m; ++i){
      cin >> q[i].L >> q[i].R;
      q[i].L--;
      q[i].R--;
      q[i].index = i;
      q[i].result = 0;
   }
   queryResults(a, n, q, m); 
   printResults(q, m); 
   return 0; 
}