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

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using static System.Console;
using static System.Math;
 
public class Solve{
    static public int mod = 1000000007;
    static public string al = "abcdefghijklmnopqrstuvwxyz";
    public static void Main(){
        // •ûj
        //
        var tn = inta();
        var n = tn[0];
        var q = tn[1];
        var a = inta();
        var l = new int[q];
        var r = new int[q];
        var tl = new int[q];
        var tr = new int[q];
        for(int i=0;i<q;i++){
            var tmp = inta();
            l[i] = tmp[0];
            r[i] = tmp[1];
            tl[i] = l[i];
            tr[i] = r[i];
        }
        Array.Sort(tr,tl);
        //WriteLine(string.Join(" ",tl));
        //WriteLine(string.Join(" ",tr));
        
        var bit = new BIT(n);
        var nowr = 1;
        var dic = new Dictionary<string,long>();
        var last = new int[500001];
        for(int i=0;i<=500000;i++){
            last[i] = -1;
        }
        for(int i=1;i<=q;i++){
            
            while(tr[i-1] >= nowr){
                //WriteLine($"{tr[i-1]} {nowr}");
                if(last[a[nowr-1]] == -1){
                    last[a[nowr-1]] = nowr;
                    bit.Change(nowr,1);
                }else{
                    bit.Change(last[a[nowr-1]],-1);
                    last[a[nowr-1]] = nowr;
                    bit.Change(nowr,1);
                }
                nowr++;
                //WriteLine(tr[i-1]);
                //WriteLine(nowr);
            }
            //WriteLine(bit.Query(tl[i-1],tr[i-1]));
            var key = tl[i-1].ToString() + "-" + tr[i-1].ToString();
            if(!dic.ContainsKey(key)){
                dic.Add(key,bit.Query(tl[i-1],tr[i-1]));
            }
        }
        
        var ans = new List<long>();
        for(int i=0;i<q;i++){
            var key = l[i].ToString() + "-" + r[i].ToString();
            ans.Add(dic[key]);
        }
        WriteLine(string.Join("\n",ans));

        
	
    }
    public static void swap(ref int a,ref int b){int temp = a;a= b;b = temp;}
    static void charswap(ref char a,ref char b){char temp = a;a= b;b = temp;}
    static int ncr(int n,int r){if(n<r)return 0;r = Min(r,n-r);long nn = 1;for(int i=n-r+1;i<=n;i++){nn = nn*i%mod;}long rr = 1;for(int i=1;i<=r;i++){rr = rr*i%mod;}rr = square((int)rr,mod-2);nn = nn * rr %mod;return (int)nn;}
    // a^b mod
    static int square(int a,int b){string binary = Convert.ToString(b,2);int bileng = binary.Length;long a_power = a;long value = 1;for(int i=bileng-1;i>=0;i--){if(binary[i] == '1'){value = value*a_power%mod;}a_power = a_power*a_power%mod;}return (int)value;}
    static int square2(int a,int b){long output = 1;var list = new List<long>();int sh = 1;long n = a;list.Add(a);while(sh < b){sh *= 2;n = n*n%mod;list.Add(n);}for(int i=list.Count-1;i>=0;i--){if(b > sh){b -= sh;sh /= 2;output = output*list[i]%mod;}}return (int)output;}
    //Šeí“Çæ
    static string rstr(){ return ReadLine(); }
    static int rint(){ return int.Parse(ReadLine()); }
    static long rlong(){ return long.Parse(ReadLine()); }
    static string[] stra(){ return ReadLine().Split(' '); }
    static char[] chara(){ string[] a=stra();string b="";for(int i=0;i<a.Length;i++){b+=a[i];}return b.ToCharArray();}
    static int[] inta(){ string[] read_str_array = ReadLine().Split(' '); int[] return_int_array = new int[read_str_array.Length]; for(int countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_int_array[countup_i] = int.Parse(read_str_array[countup_i]); } return return_int_array; }
    static int[,] inta2(int num_array,int in_array){ int[,] int_array2 = new int[num_array,in_array]; for(int i=0;i<num_array;i++){ int[] temp_array = inta(); for(int j=0;j<in_array;j++){ int_array2[i,j] = temp_array[j]; } } return int_array2; }
    static long[] longa(){ string[] read_str_array = ReadLine().Split(' '); long[] return_long_array = new long[read_str_array.Length]; for(long countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_long_array[countup_i] = long.Parse(read_str_array[countup_i]); } return return_long_array; }
    static double[] doublea(){ string[] read_str_array = ReadLine().Split(' '); double[] return_double_array = new double[read_str_array.Length]; for(long countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_double_array[countup_i] = double.Parse(read_str_array[countup_i]); } return return_double_array; }
    // -----------------------------
    static long GCD(long a,long b){ if(a < b){ long temp = a; a = b; b = temp; } if(a % b == 0){ return b; } else{ long temp = b; b = a%b; a = temp; return GCD(a,b); } }
    static long LCM(long a,long b){ return a * b / GCD(a,b); }
    static void WriteArray(int[,] a,int b,int c){for(int i=0;i<b;i++){for(int j=0;j<c;j++){if(j!=0) Write(" ");Write(a[i,j]);}WriteLine();}}
}
class BIT{
    private long[] _bit;
    private int leng;
    
    public BIT(int a){
        _bit = new long[a+1];
        leng = _bit.Length;
    }
    
    public void Change(int a,long b){
        while(a <= leng){
            _bit[a] += b;
            a += -a & a;
        }
    }
    
    public long Query(int a,int b){
        a--;
        long ret = 0;
        while(b > 0){
            ret += _bit[b];
            b -= -b & b;
        }
        while(a > 0){
            ret -= _bit[a];
            a -= -a & a;
        }
        return ret;
    }
}