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# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;

delegate T Function<T>(T v1, T v2);

class SegTree<T>
{

    public int Count { get; }
    
    int n_layer;
    int[] segsize;
    T[][] data;

    Function<T> function;
    
    public SegTree(int N, Function<T> function, T fill=default(T))
    {
        Count=N;

        this.function=function;
        
        n_layer=1;
        for(int k=1; k<N; k<<=1) n_layer+=1;

        segsize = new int[n_layer];
        data = new T[n_layer][];
        for(int l=0; l<n_layer; ++l) {
            segsize[l] = 1<<(n_layer-1-l);
            data[l] = new T[1<<l];
            for(int j=0; j<(1<<l); ++j) data[l][j]=fill;
        }
    }
    
    public void Update(int index, T value) {
        data[n_layer-1][index] = value;
        
        for(int l=n_layer-2; l>=0; --l) {
            index = index/2;
            data[l][index] = function(data[l+1][index*2], data[l+1][index*2+1]);
        }
    }

    public T Query(int ibgn, int iend, int l=0) {
        int ssize = segsize[l];
        if(ibgn%ssize==0 && iend-ibgn==ssize) return data[l][ibgn/ssize];

        int imid = ibgn - ibgn%ssize + ssize/2;
        if(iend<=imid || imid<=ibgn) return Query(ibgn, iend, l+1);
        return function(Query(ibgn, imid, l+1), Query(imid, iend, l+1));
    }
    

    public void Print()
    {
        Console.WriteLine($"Count   : {Count}");
        Console.WriteLine($"n_layer : {n_layer}");
        for(int l=0; l<n_layer; ++l) {
            Console.WriteLine($"[{l}] "+string.Join(" ", data[l]));
        }
    }
}


class Program
{
    static void Main()
    {
        var str = Console.ReadLine().Split(" ");
        var N = int.Parse(str[0]);
        var Q = int.Parse(str[1]);

        var C = new int[N];
        str = Console.ReadLine().Split(" ");
        for(int i=0; i<N; ++i) C[i] = int.Parse(str[i]);
        
        var LR = new List<List<int>>();
        for(int q=0; q<Q; ++q) {
            str = Console.ReadLine().Split(" ");
            int l = int.Parse(str[0]);
            int r = int.Parse(str[1]);

            LR.Add(new List<int>{q, l, r});
        }

        LR.Sort((x, y) => x[2]-y[2]);

        var I = new int[N+1];
        for(int i=0; i<I.Length; ++i) I[i] = -1;
        
        var st = new SegTree<int>(N, (x, y) => x+y, 0);

        var ans = new int[Q];
        int j = 0;
        for(int iq=0; iq<Q; ++iq) {
            int q = LR[iq][0];
            int l = LR[iq][1];
            int r = LR[iq][2];

            for(; j<r; ++j) {
                int c = C[j];

                int iprev = I[c];
                I[c] = j;

                if(iprev!=-1) st.Update(iprev, 0);
                st.Update(j, 1);
            }
            ans[q] = st.Query(l-1,r);
        }

        Console.WriteLine(String.Join("\n", ans));
        
    }
}