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

object Main extends App {
  val sc = new FastScanner(System.in)
  val n, q = sc.nextInt()
  val c = Array.fill(n)(sc.nextInt()-1)
  val lr = List.fill(q)((sc.nextInt()-1, sc.nextInt()-1))
  val ans = Array.fill(q)(0)
  val pw = new java.io.PrintWriter(Console.out)

  val pos = Array.fill(n)(-1)
  val st = new SegmentTree[Int](List.fill(n)(0), n, _+_, 0)
  var rPrev = -1

  for (((l, r), idx) <- lr.zipWithIndex.sortBy(_._1._2)) {
    for (i <- rPrev+1 to r) {
      val p = pos(c(i))
      pos(c(i)) = i
      if (p != -1) {
        st.update(p, 0)
      }
      st.update(i, 1)
    }
    rPrev = r
    ans(idx) = st.query(l, r+1)
  }

  ans.foreach(pw.println)
  pw.flush()
}

class SegmentTree[A: reflect.ClassTag](seq: List[A], n: Int, op: (A,A) => A, unit: A) {
  private def par(idx: Int): Int = (idx - 1) / 2
  private def left(idx: Int): Int = 2 * idx + 1
  private def right(idx: Int): Int = 2 * idx + 2

  private val tree = Array.fill(2*n - 1)(unit)

  for ((a, idx) <- seq.zipWithIndex) {
    tree(idx + n - 1) = a
  }

  for (idx <- n-2 to 0 by -1) {
    tree(idx) = op(tree(left(idx)), tree(right(idx)))
  }

  def query(l: Int, r: Int): A = {
    var lp = l + n - 1
    var rp = r + n - 1
    var lRes, rRes = unit

    while (lp < rp) {
      if ((lp & 1) == 0) {
        lRes = op(lRes, tree(lp))
      }
      if ((rp & 1) == 0) {
        rp = rp - 1
        rRes = op(tree(rp), rRes)
      }
      lp >>= 1
      rp >>= 1
    }

    op(lRes, rRes)
  }

  def update(idx: Int, a: A): Unit = {
    var i = idx + n - 1
    tree(i) = a
    while (i > 0) {
      i = par(i)
      tree(i) = op(tree(left(i)), tree(right(i)))
    }
  }
}


class FastScanner(source: java.io.InputStream) {
  val buf = new Array[Byte](1024)
  var now, end = 0

  def isPrintable(b: Byte): Boolean = 33 <= b && b <= 126
  def isNum(b: Byte): Boolean = 48 <= b && b <= 57

  def hasNextByte: Boolean = {
    if (now < end) {
      true
    } else {
      now = 0
      end = source.read(buf)
      end > 0
    }
  }

  def nextByte(): Byte = {
    if (hasNextByte) {
      val b = buf(now)
      now += 1
      b
    } else {
      -1
    }
  }

  def hasNext: Boolean = {
    while (hasNextByte && !isPrintable(buf(now))) {
      now += 1
    }
    hasNextByte
  }

  def next(): String = {
    if (hasNext) {
      val sb = new StringBuilder()
      var b = nextByte()
      while (isPrintable(b)) {
        sb += b.toChar
        b = nextByte()
      }
      sb.toString
    } else {
      throw new NoSuchElementException()
    }
  }

  def nextInt(): Int = {
    nextLong().toInt
  }

  def nextLong(): Long = {
    if (hasNext) {
      var b = nextByte()
      var sign = 1
      var n = 0L
      if (b == '-') {
        sign = -1
        b = nextByte()
      }
      while (isNum(b)) {
        n = n * 10 + (b - 48)
        b = nextByte()
      }
      sign * n
    } else {
      throw new NoSuchElementException()
    }
  }

  def nextDouble(): Double = next().toDouble
}