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: Time Limit Exceeded)

#include <iostream>
#include <climits>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

void print(set<long> &x) {
    for (auto e: x) {
	cout << e << " ";
    }
    cout << "\n";
}


int main() {
    long n = LONG_MIN;
    cin >> n;
    long q = LONG_MIN;
    cin >> q;
    vector<long> c(n);
    for (int i = 0; i < n; ++i) {
	cin >> c[i];
    }

    long n_cut = 1;
    while (n_cut < n) {
	n_cut *= 2;
    }

    vector<set<long>> data(2*n_cut, set<long> {});

    for (int i = 0; i < n; ++i) {
	data[n_cut + i] = set<long> {c[i]};
    }

    for (int i = n_cut - 1; i >= 1; --i) {
	set_union(data[2*i].begin(), data[2*i].end(),
		  data[2*i+1].begin(), data[2*i+1].end(),
		  inserter(data[i], data[i].begin()));
    }

//    for (int i = 0; i < 2*n_cut; ++i) {
//	cout << "i: " << i << ": ";
//	print(data[i]);
//    }
    
    for (int j = 0; j < q; ++j) {
	long l = LONG_MIN;
	long r = LONG_MAX;
	cin >> l;
	cin >> r;
	l = l-1;
	r = r-1;
	//cout << "l " << l << " " << "r " << r << "\n"; 
	long lnode = n_cut + l;
	long rnode = n_cut + r;
	set<long> res_left = data[lnode];
	set<long> res_right = data[rnode];
	while (lnode < rnode) {
	    //cout << "entering lnode " << lnode << ", rnode " << rnode << "\n";
	    long ldir = lnode % 2;
	    long rdir = rnode % 2;
	    set<long> temp {};

	    if (ldir == 0 && lnode + 1 != rnode) {
		set_union(res_left.begin(), res_left.end(),
			  data[lnode+1].begin(), data[lnode+1].end(),
			  inserter(temp, temp.begin()));
		res_left = temp;
	    }
	    temp = set<long> {};
	    if (rdir == 1 && rnode - 1 != lnode) {
		set_union(res_right.begin(), res_right.end(),
			  data[rnode-1].begin(), data[rnode-1].end(),
			  inserter(temp, temp.begin()));
		res_right = temp;
	    }
	    lnode = lnode / 2;
	    rnode = rnode / 2;
	}

	set<long> temp = set<long> {};
	set_union(res_left.begin(), res_left.end(),
		  res_right.begin(), res_right.end(),
		  inserter(temp, temp.begin()));
	cout << temp.size() << "\n";
    }
}