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 <math.h>
using namespace std;
typedef long long int lli;
typedef unsigned long long int uli;
typedef long double Lf;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define fastIO  std::ios::sync_with_stdio(false);cin.tie(NULL)
#define mod 1000000007
#define N 500005
#define NN 2005
#define SZ(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define loop(i,s,n) for(int i=(s);i<(n);i++)
#define loopr(i,n,s) for(int i=(n)-1;i>=(s);i--)
#define pb push_back
#define o2(a,b) cout<<(a)<<" "<<(b)<<endl
#define o3(a,b,c) cout<<(a)<<" "<<(b)<<" "<<(c)<<endl
#define o4(a,b,c,d) cout<<(a)<<" "<<(b)<<" "<<(c)<<" "<<(d)<<endl
#define cl cout<<endl
#define r0 return 0
#define e0 exit(0)
#define x first
#define y second

inline lli modadd(lli n,lli m,lli p=mod){
    return ((n+m)%p+p)%p;
}

inline lli modsub(lli n,lli m,lli p=mod){
    return ((n-m+p)%p+p)%p;
}

inline lli modpro(lli n,lli m,lli p=mod){
    return (((n%p)*(m%p))%p+p)%p;
}

uli powe(lli x,lli y){
    uli res = 1;
    while (y > 0) {
        if (y & 1)
            res = res * x;
        y = y >> 1;
        x = x * x;
    }
    return res;
}

lli modpow(lli x,lli y,lli p=mod){
    lli res = 1;
    while (y > 0) {
        if (y & 1)
            res = modpro(res , x, p);
        y = y >> 1;
        x = modpro(x , x, p);
    }
    return res;
}

inline lli modInverse(lli n, lli p=mod)
{
    if(n==1) return 1;
    return modpow(n, p-2, p);
}

inline lli moddiv(lli n,lli m,lli p=mod){
    return modpro(n,modInverse(m,p),p);
}

inline lli modadd3(lli x, lli y, lli z,lli p=mod){
    return modadd(modadd(x,y,p),z,p);
}

inline lli modadd4(lli x, lli y, lli z, lli w,lli p=mod){
    return modadd(modadd(x,y,p),modadd(z,w,p),p);
}

inline lli modnCr(lli fac[], int n, int r, lli p=mod)
{
    if (r==0) return 1;
    return modpro(fac[n],modInverse(modpro(fac[r],fac[n-r],p),p),p);
}


template <typename T>
void printArr(T *arr, int s, int n){
    for(int i=s;i<=n;i++){

        cout<<arr[i]<<" ";
    }cout<<endl;
}

//template<class X, class Y, class Z>
//struct triple {
//    X x;
//    Y y;
//    Z z;
//
//     friend bool operator<(triple a, triple b)
//    {
//        if(a.x!=b.x) return a.x<b.x;
//        else if(a.y!=b.y) return a.y<b.y;
//        else return a.z<=b.z;
//    }
//};
//
//
//template<class X, class Y, class Z, class W>
//class quad {
//    public:
//    X x;
//    Y y;
//    Z z;
//    W w;
//
//     friend bool operator<(quad a, quad b)
//    {
//        if(a.x!=b.x) return a.x<b.x;
//        else if(a.y!=b.y) return a.y<b.y;
//        else if(a.z!=b.z)return a.z<b.z;
//        else return a.w<b.w;
//    }
//};


//
//uli choose(uli n, uli k){
//uli res = 1;
//
//    // Since C(n, k) = C(n, n-k)
//    if ( k > n - k )
//        k = n - k;
//
//    // Calculate value of
//    // [n * (n-1) *---* (n-k+1)] / [k * (k-1) *----* 1]
//    for (uli i = 0; i < k; ++i)
//    {
//        res *= (n - i);
//        res /= (i + 1);
//    }
//
//    return res;
//}
//

//
//  vector<vector<pii>> adj;
//   //vector<int> dist;
//   vector<int> d;
////   vector<bool> visited;
////     vector<int> pa;
//   //queue<int> q;
//
//  class Graph{
//
//   public:
//      int V;
//
//  Graph(int V){
//      this->V = V;
//      adj.resize(V);
////        visited.resize(V);
//      //color.resize(V);
//      //dist.resize(V);
//        d.resize(V);
//     //// dist.resize(V);
////     pa.resize(V);
//
//  }
//
//  ~Graph(){
// 	  adj.clear();
// 	  //visited.clear();
// 	 // color.clear();
// 	 // dist.clear();
////    pa.clear();
// 	  //dist.clear();
//// 	  visited.clear();
//d.clear();
//
//
//  }
//
//
//  void addEdge(int a, int b)
//  {
//      adj[a].pb(b);
//      adj[b].pb(a);
//      //adj[b].pb({a,in});
//  }
//
// //  void dfs(int x){
// //    //  color[x]=1;
// //   visited[x]=1;
// //      for(auto u: adj[x]){
// //          if(visited[u]) continue;
// //
// //          dfs(u);
// //      }
// //
// //  }
// //
// //
// //
// //
// //
//  // void dfsTree(int x, int p){
//  //     for(auto u: adj[x]){
//  //         if(u==p) {continue;}
//  //         dfsTree(u,x);
//  //     }
//  // }
//
//
//void dijkstra(int s) {
//    d.assign(n, INF);
//    d[s] = 0;
//    set<pair<int, int>> q;
//    q.insert({0, s});
//    while (!q.empty()) {
//        int v = q.begin()->second;
//        q.erase(q.begin());
//        for (auto edge : adj[v]) {
//            int to = edge.first;
//            int len = edge.second;
//            if (d[v] + len < d[to]) {
//                q.erase({d[to], to});
//                d[to] = d[v] + len;
//                q.insert({d[to], to});
//            }
//        }
//    }
//}
//
//
////  void bfs(int x){
////      queue<int> q;
////      visited[x]=1;
////      q.push(x);
////      //dist[x]=0;
////      while(!q.empty()){
////          int s = q.front();
////          q.pop();
////
////          for(auto u : adj[s]){
////
////              if(visited[u]) continue;
////              pa[u]=s;
////              visited[u]=1;
////              //dist[u.x]=dist[s]+1;
////              q.push(u);
////          }
////      }
////  }
//
// //pair<int,int> farthest(int start){
// //    vector<int> dist(V,INT_MAX);
// //
// //    q.push(start);
// //    dist[start]=0;
// //    while(!q.empty()){
// //        int u = q.front();
// //        q.pop();
// //        for(int child: adj[u]){
// //            //if(keep[child])
// //            if(dist[child] > dist[u]+1) {
// //                dist[child] = dist[u]+1;
// //                q.push(child);
// //            }
// //        }
// //    }
// //    int big=-1,mi=-1;
// //    for(int i=1;i<n+1;i++){
// //        //if(keep[i])
// //        {
// //            if(dist[i]>big){
// //                big=dist[i];mi=i;
// //            }
// //        }
// //    }
// //    return make_pair(big,mi);
// //}
//
//
// //  int connectedcomponents(int n){
// //      int ans=0;
// //      loop(i,1,n+1){
// //          if(!visited[i]){
// //              ans++;
// //              dfs(i);
// //          }
// //
// //      }
// //      return ans;
// //  }
//
//  };


//template <typename T>
//T findpowerfactorial(T n,T p)
//{
//    T x = 0;
//    while (n)
//    {
//        n /= p;
//        x += n;
//    }
//    return x;
//}
//

//vector<pair<lli,int>> v;
//void primeFactors(lli n)
//{
//    v.clear();
//    int c=0;
//    while (n % 2 == 0)
//    {
//        n = n/2;
//        c++;
//    }
//    if(c>0) v.pb({2,c});
//
//
//    for (lli i = 3; i*i <= n; i = i + 2)
//    {   c=0;
//
//        while (n % i == 0)
//        {
//            n = n/i;
//            c++;
//        }
//        if(c>0)v.pb({i,c});
//
//    }
//    if (n > 2)
//        v.pb({n,1});
//}

// lli fac_[N];
// void fac_init(int n){
//    fac_[0]=1;
//    loop(i,1,n+1)fac_[i]=modpro(fac_[i-1],i);
// }
//
/*BITMASK
for( int inum = 0 ; inum < ( 1 << n ) ; ++ inum ) {
     for ( int pos = 0; pos < n ; ++pos ) {
         if (  inum & ( 1 << pos )  ){
              results[inum] += s [pos] ; //DO SOMETHING
         }
     }
}
*/
pair<pii,int> p[N];
int a[N];
int tl=0,tr=-1;
lli cnt[N];
int ans[N];
lli bit[N];
int n,q;
int last_visit[N]; 
void update(int idx, int val) 
{ 
    for (; idx <= n; idx += idx&-idx) 
        bit[idx] += val; 
} 
  
// querying the bit array 
int query(int idx) 
{ 
    int sum = 0; 
    for (; idx>0; idx-=idx&-idx) 
        sum += bit[idx]; 
    return sum; 
} 
bool comp(pair<pii,int> x, pair<pii,int> y){
    return x.x.y<y.x.y;
}
int query_counter = 0; 
int main(){
    fastIO;
    int erer=1;
    // cin>>erer;
    loop(erer2,1,erer+1){
        cin>>n>>q;
        loop(i,0,n) cin>>a[i];
        memset(last_visit, -1, sizeof(last_visit)); 
        loop(i,0,q){
            cin>>p[i].x.x>>p[i].x.y;
            p[i].x.x--;
            p[i].x.y--;
            p[i].y=i;
        }
        sort(p,p+q, comp);
        
        
        for (int i=0; i<n; i++) 
    {
        if (last_visit[a[i]] !=-1) 
            update (last_visit[a[i]] + 1, -1); 

        // Setting last_visit[arr[i]] as i and updating 
        // the bit array accordingly 
        last_visit[a[i]] = i; 
        update(i + 1, 1); 

        // If i is equal to r of any query  store answer 
        // for that query in ans[] 
        while (query_counter < q && p[query_counter].x.y == i) 
        { 
            ans[p[query_counter].y] = 
                    query(p[query_counter].x.y + 1)- 
                    query(p[query_counter].x.x); 
            query_counter++; 
        } 

    }
		

		loop(i,0,q) cout<<ans[i]<<"\n";
    }
    return 0;
}