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: Wrong Answer)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define REP(k, n) for (ll k = 0; k < (ll)(n); ++k)
#define REPREV(k, n) for (ll k = (ll)(n)-1; k >= 0; --k)
#define FOR(k, a, b) for (ll k = (ll)(a); k < (ll)(b); ++k)
#define FORREV(k, a, b) for (ll k = (ll)(b)-1; k >= (ll)(a); --k)
#define FOREACH(e, v) for (auto& e : v)

#define TGET(t, i) get<i>(t)
#define TSET(t, i, a) get<i>(t) = a
// MinHeap - priority_queue<ll, vll, greater<ll>> pq;

#define EVEN(n) ((n)&1) == 0
#define ODD(n) ((n)&1) == 1

#define SORT(v) sort(v.begin(), v.end())
#define SORTREV(v) sort(v.rbegin(), v.rend())
#define SHUFFLE(v) random_shuffle(v.begin(), v.end())
//srand(unsigned(time(0)));

#define REMOVEAT(v, i) v.erase(v.begin() + i)
#define REVERSE(v) reverse(v.begin(), v.end())

ostream& operator<<(ostream& str, const pll& p) {
    str << p.first << " " << p.second;
    return str;
}

template <typename T>
void join(T& arr, string sep) {
    bool first = true;
    for (auto t : arr) {
        if (first) {
            first = false;
            cout << t;
        } else {
            cout << sep << t;
        }
    }
    cout << "\n";
}

const ll md = 1e9 + 7;
ll MOD(ll x) {
    ll r = x % md;
    if (r < 0) {
        r += md;
    }
    return r;
}

#define POS "POSSIBLE"
#define IMPOS "IMPOSSIBLE"

// #define INF LLONG_MAX
// #define MINF LLONG_MIN
#define INF 1e18
#define MINF -INF


int block; 
  
// Structure to represent a query range 
struct Query 
{ 
    int L, R; 
}; 
  
// Function used to sort all queries so that all queries  
// of the 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; 
} 
  
// Prints sum 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 sum 
    int currL = 0, currR = 0; 
    int currSum = 0; 
    int count[n];
    for (int i = 0; i < n; i++) {
        count[i] = 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) 
        { 
            count[a[currL]]--;
            if (count[a[currL]] == 0)
                currSum--;
            currL++; 
        } 
  
        // Add Elements of current Range 
        while (currL > L) 
        { 
            count[a[currL-1]]++;
            if (count[a[currL-1]] == 1)
                currSum++;
            currL--; 
        } 
        while (currR <= R) 
        { 
            count[a[currR]]++;
            if (count[a[currR]] == 1)
                currSum++;
            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 
        while (currR > R+1) 
        { 
            count[a[currR-1]]--;
            if (count[a[currR-1]] == 0)
                currSum--;
            currR--; 
        } 
  
        // Print sum of current range 
        cout << currSum << endl; 
    }
}

void solve() {
    ll n, q;
    cin >> n >> q;
    ll res = 0;
    int a[n];
    REP(i, n) {
        cin >> a[i];
        a[i]--;
    }
    Query qqq[q];
    REP(qq, q) {
        ll l, r;
        cin >> qqq[qq].L >> qqq[qq].R;
        qqq[qq].L--;
        qqq[qq].R--;
    }
    queryResults(a, n, qqq, q);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int tt = 1;
    // cin >> tt;
    for (int t = 1; t <= tt; t++) {
        // cout << "Case #" << t << ": ";
        solve();
    }
    //cin.rdbuf()->in_avail()
    return 0;
}