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 Kotlin (1.3.71) (judge verdict: Time Limit Exceeded)

import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.math.*
import kotlin.system.exitProcess

@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar()
        else c
    }
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(true) {
            when(c) {
                '\n', Char.MIN_VALUE -> return@buildString
                else -> {
                    append(c)
                    c = readChar()
                }
            }
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

fun main() {

    val (n, queryCount) = readIntArray(2)
    val a = readIntArray(n)

    val segment = Array(4*n) { mutableSetOf<Int>()}

    fun build(v: Int, left: Int, right: Int) {
        if (left == right) {
            segment[v].add(a[left])
        } else {
            val mid = left + (right - left) / 2

            val s1 = build(2*v + 1, left, mid)
            val s2 = build(2*v + 2, mid + 1, right)
            segment[v].addAll(segment[2*v + 1])
            segment[v].addAll(segment[2*v + 2])
        }
    }

    build(0, 0, n - 1)

    fun query(v: Int, left: Int, right: Int, queryLeft: Int, queryRight: Int): Set<Int> {
        if (left == queryLeft && right == queryRight) {
            return segment[v]
        }

        val mid = left + (right - left) / 2
        if (queryRight <= mid) {
            return query(2 * v + 1, left, mid, queryLeft, queryRight)
        }

        if (queryLeft > mid) {
            return query(2* v + 2, mid + 1, right, queryLeft, queryRight)
        }

        val result = mutableSetOf<Int>()
        result.addAll(query(2*v + 1, left, mid, queryLeft, mid))
        result.addAll(query(2*v + 2, mid + 1, right, mid + 1, queryRight))
        return result
    }

    for (query in 0 until queryCount) {
        val (a, b) = readIntArray(2)
        println(query(0, 0, n -1, a - 1, b - 1).size)
    }
}