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

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<ctime>
#include<cmath>
#include<utility>
#include<cstdlib>
#include<bitset>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iomanip>
#include<assert.h>
#include<string.h>

#define DB(x) cout<<#x<<"="<<x<<endl;

using namespace std;

const int MAXN = 1e5 + 5;

const int MAXS = 2e7;
int root[MAXN], root2[MAXN];

//Begin persistent segment tree
int lch[MAXS], rch[MAXS], sum2[MAXS], cnt;

int new_node (int val)
{
    assert(cnt < MAXS);
    sum2[cnt] = val;
    return cnt++;
}

int new_node (int l, int r, bool s)
{
    lch[cnt] = l;
    rch[cnt] = r;

    return new_node(s ? sum2[l] + sum2[r] : max(sum2[l], sum2[r]));
}

int build (int b, int e)
{
    if (b == e)
        return new_node(0);

    int m = (b + e) / 2;
    return new_node(build(b, m), build(m + 1, e), false);
}

int update2 (int v, int b, int e, int p, int val, bool s)
{
    if (b > p || e < p)
        return v;

    if (b == e)
        return new_node(val);

    int m = (b + e) / 2;
    int l = update2(lch[v], b, m, p, val, s),
        r = update2(rch[v], m + 1, e, p, val, s);

    return new_node(l, r, s);
}

int query (int v, int b, int e, int l, int r, bool s)
{
    if (e < l || b > r)
        return 0;

    if (l <= b && e <= r)
        return sum2[v];

    int m = (b + e) / 2;

    if (s)
        return  query(lch[v], b, m, l, r, s) + query(rch[v], m + 1, e, l, r, s);
    else
        return max(query(lch[v], b, m, l, r, s), query(rch[v], m + 1, e, l, r, s));
}

//End persistent segment tree


int n, a[MAXN], next_pos[MAXN], forw[MAXN], q, l, r, last[MAXN];
int pos[MAXN];

void update (int r, int a, int b)
{
    root2[a] = update2(r, 0, MAXN - 1, a, b, 0);
}

int dquery (int l, int r)
{
    return query(root[r + 1], 0, MAXN - 1, l + 1, r + 1, 1);
}

int main()
{
    cin.sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> q;

    for (int i = 0; i < n; ++i)
        cin >> a[i];

    root[0] = build(0, MAXN - 1);
    root2[n] = build(0, MAXN - 1);

    for (int i = 1; i <= n; ++i)
    {
        int r = root[i - 1];
        int a = ::a[i - 1];

        if (pos[a])
            r = update2(r, 0, MAXN - 1, pos[a], 0, 1);

        root[i] = update2(r, 0, MAXN - 1, i, 1, 1);
        pos[a] = i;
    }

    memset(forw, -1, sizeof forw);

    for (int i = n - 1; i >= 0; --i)
    {
        if (forw[a[i]] == -1)
        {
            update(root2[i + 1], i, MAXN - 2);
            next_pos[i] = MAXN - 2;
            last[i] = MAXN - 2;
        }
        else
        {
            int idx = forw[a[i]];
            int rot = update2(root2[i + 1], 0, MAXN - 1, idx, 0, 0);
            int r = next_pos[idx];
            next_pos[i] = idx;

            if (r == MAXN - 2 || r - idx != idx - i)
            {
                update(rot, i, r);
                last[i] = r;
            }
            else
            {
                update(rot, i, last[idx]);
                last[i] = last[idx];
            }
        }

        forw[a[i]] = i;
    }


    for (int i = 0; i < q; ++i)
    {
        cin >> l >> r;
        --l, --r;
        int ans = dquery(l, r);
        int cnt = query(root2[l], 0, MAXN - 1, l, r, 0);
        ans += cnt <= r;
        cout << ans << endl;
    }
    return 0;
}