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

#[allow(unused_imports)]
use {
   proconio::{fastout, input, marker::*},
   std::cmp::*,
   std::collections::*,
};

#[fastout]
fn main() {
   input! {
      n: usize,
      qn: usize,
      c: [Usize1; n],
      lr: [(Usize1, usize); qn]
   }
   let mut q = vec![];
   for (i, (l, r)) in lr.iter().enumerate() {
      q.push((*l, *r, i));
   }
   q.sort();

   let mut mem = BTreeMap::new();
   for (l, r) in lr {
      let b = dfs(l, r, n, &c, &mut mem);
      println!("{}", b.count_ones());
   }
}

fn dfs(
   l: usize,
   r: usize,
   n: usize,
   c: &[usize],
   mem: &mut BTreeMap<(usize, usize), BitSet>,
) -> BitSet {
   if let Some(b) = mem.get(&(l, r)) {
      return b.clone();
   }
   let mut bit = BitSet::new(n);
   if r - l == 1 {
      bit.set(c[l], true);
      return bit;
   }
   let m = (l + r) / 2;
   bit |= &dfs(l, m, n, c, mem);
   bit |= &dfs(m, r, n, c, mem);
   if n < (r - l) * (r - l) {
      mem.insert((l, r), bit.clone());
   }
   return bit;
}

const TRUE: &bool = &true;
const FALSE: &bool = &false;
#[derive(Clone, Debug)]
/// Efficient bool collection
pub struct BitSet {
   buf: Vec<u64>,
   size: usize,
}
impl BitSet {
   #[allow(dead_code)]
   pub fn new(size: usize) -> BitSet {
      BitSet {
         buf: vec![0; (size + 63) / 64],
         size,
      }
   }
   #[allow(dead_code)]
   pub fn set(&mut self, i: usize, b: bool) {
      assert!(i < self.size);
      if b {
         self.buf[i >> 6] |= 1 << (i & 63);
      } else {
         self.buf[i >> 6] &= !(1 << (i & 63));
      }
   }
   #[allow(dead_code)]
   pub fn count_ones(&self) -> u32 { self.buf.iter().map(|x| x.count_ones()).sum() }
   #[allow(dead_code)]
   fn chomp(&mut self) {
      let r = self.size & 63;
      if r != 0 {
         if let Some(x) = self.buf.last_mut() {
            let d = 64 - r;
            *x = (*x << d) >> d;
         }
      }
   }
}
impl std::ops::Index<usize> for BitSet {
   type Output = bool;
   fn index(&self, index: usize) -> &bool {
      [FALSE, TRUE][(self.buf[index >> 6] >> (index & 63)) as usize & 1]
   }
}
#[allow(clippy::suspicious_op_assign_impl)]
impl std::ops::ShlAssign<usize> for BitSet {
   fn shl_assign(&mut self, x: usize) {
      let q = x >> 6;
      let r = x & 63;
      if q >= self.buf.len() {
         for x in &mut self.buf {
            *x = 0;
         }
         return;
      }
      if r == 0 {
         for i in (q..self.buf.len()).rev() {
            self.buf[i] = self.buf[i - q];
         }
      } else {
         for i in (q + 1..self.buf.len()).rev() {
            self.buf[i] = (self.buf[i - q] << r) | (self.buf[i - q - 1] >> (64 - r));
         }
         self.buf[q] = self.buf[0] << r;
      }
      for x in &mut self.buf[..q] {
         *x = 0;
      }
      self.chomp();
   }
}
impl std::ops::Shl<usize> for BitSet {
   type Output = Self;
   fn shl(mut self, x: usize) -> Self {
      self <<= x;
      self
   }
}
#[allow(clippy::suspicious_op_assign_impl)]
impl std::ops::ShrAssign<usize> for BitSet {
   fn shr_assign(&mut self, x: usize) {
      let q = x >> 6;
      let r = x & 63;
      if q >= self.buf.len() {
         for x in &mut self.buf {
            *x = 0;
         }
         return;
      }
      if r == 0 {
         for i in 0..self.buf.len() - q {
            self.buf[i] = self.buf[i + q];
         }
      } else {
         for i in 0..self.buf.len() - q - 1 {
            self.buf[i] = (self.buf[i + q] >> r) | (self.buf[i + q + 1] << (64 - r));
         }
         let len = self.buf.len();
         self.buf[len - q - 1] = self.buf[len - 1] >> r;
      }
      let len = self.buf.len();
      for x in &mut self.buf[len - q..] {
         *x = 0;
      }
   }
}
impl std::ops::Shr<usize> for BitSet {
   type Output = Self;
   fn shr(mut self, x: usize) -> Self {
      self >>= x;
      self
   }
}
impl<'a> std::ops::BitAndAssign<&'a BitSet> for BitSet {
   fn bitand_assign(&mut self, rhs: &'a Self) {
      for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) {
         *a &= *b;
      }
   }
}
impl<'a> std::ops::BitAnd<&'a BitSet> for BitSet {
   type Output = Self;
   fn bitand(mut self, rhs: &'a Self) -> Self {
      self &= rhs;
      self
   }
}
impl<'a> std::ops::BitOrAssign<&'a BitSet> for BitSet {
   fn bitor_assign(&mut self, rhs: &'a Self) {
      for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) {
         *a |= *b;
      }
      self.chomp();
   }
}
impl<'a> std::ops::BitOr<&'a BitSet> for BitSet {
   type Output = Self;
   fn bitor(mut self, rhs: &'a Self) -> Self {
      self |= rhs;
      self
   }
}
impl<'a> std::ops::BitXorAssign<&'a BitSet> for BitSet {
   fn bitxor_assign(&mut self, rhs: &'a Self) {
      for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) {
         *a ^= *b;
      }
      self.chomp();
   }
}
impl<'a> std::ops::BitXor<&'a BitSet> for BitSet {
   type Output = Self;
   fn bitxor(mut self, rhs: &'a Self) -> Self {
      self ^= rhs;
      self
   }
}