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: Accepted)

#![allow(unused_imports)]
#![allow(unused_macros)]
use std::cmp::{max, min, Ordering::*};
use std::collections::*;
use std::io::{stdin, stdout, BufWriter, Read, Write};

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, $var:ident $($r:tt)*) => {
        let $var = parse_val!($it, usize);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: tt),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, u1) => {
        $it.next().unwrap().parse::<usize>().unwrap() -1
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

// #[cfg(debug_assertions)]
macro_rules! debug {
    ($( $args:expr ),*) => { eprintln!( $( $args ),* ); }
}

// #[cfg(not(debug_assertions))]
// macro_rules! debug {
//     ($( $args:expr ),*) => {
//         ()
//     };
// }

#[derive(Debug)]
pub struct CountLessThan<T> {
    dat: Vec<T>,
    n: usize,
}

fn ulog2(mut n: usize) -> usize {
    if n == 0 {
        0
    } else {
        let mut count = 0;
        while n > 1 {
            n >>= 1;
            count += 1;
        }
        count
    }
}

fn ab(n: usize) -> (usize, usize) {
    let a = ulog2(n);
    (a, n - (1 << a))
}

impl<T: Ord + Copy> CountLessThan<T> {
    pub fn new(v: Vec<T>, maxv: T) -> Self {
        let _n = v.len();
        let mut n = 1;
        while _n > n {
            n *= 2;
        }
        let md = ulog2(n);
        let mut dat = vec![maxv; (md + 1) * n + 1];
        for (i, &vi) in v.iter().enumerate() {
            dat[md * n + i + 1] = vi;
        }
        // merge
        for k in (1..n).rev() {
            let (a, b) = ab(k);
            let m = n >> a;
            let head = a * n + m * b + 1;
            let headi = (a + 1) * n + m * b + 1;
            let headj = headi + (m >> 1);
            let mut i = 0usize;
            let mut j = 0usize;
            let md2 = m >> 1;
            while i < md2 || j < md2 {
                if i == md2 || j < md2 && dat[headi + i] > dat[headj + j] {
                    dat[head + i + j] = dat[headj + j];
                    j += 1;
                } else if j == md2 || i < md2 && dat[headi + i] <= dat[headj + j] {
                    dat[head + i + j] = dat[headi + i];
                    i += 1;
                } else {
                    unreachable!()
                }
            }
        }
        Self { dat, n }
    }
    pub fn get(&self, l: usize, r: usize, query: T) -> usize {
        let mut l = l + self.n;
        let mut r = r + self.n;
        let mut countr = 0;
        let mut countl = 0;
        let cmp = |x: &T| match x.cmp(&query) {
            Equal => Less,
            d => d,
        };
        let mut a = ulog2(self.n);
        let mut m = 1;
        while l < r {
            if l & 1 != 0 {
                let b = l - (1 << a);
                let head = a * self.n + m * b + 1;
                countl += self.dat[head..(head + m)]
                    .binary_search_by(cmp)
                    .unwrap_or_else(|x| x);
                l += 1;
            }
            if r & 1 != 0 {
                let b = r - 1 - (1 << a);
                let head = a * self.n + m * b + 1;
                countr += self.dat[head..(head + m)]
                    .binary_search_by(cmp)
                    .unwrap_or_else(|x| x);
            }
            l >>= 1;
            r >>= 1;
            a -= 1;
            m <<= 1;
        }
        countl + countr
    }
}

use std::time::SystemTime;

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    parse!(it, n: usize, q: usize, c: [usize; n]);
    let mut nxt = vec![n; n];
    let mut last = HashMap::new();
    for i in (0..n).rev() {
        let e = last.entry(c[i]).or_insert(n);
        nxt[i] = *e;
        *e = i;
    }

    let start = SystemTime::now();
    let cs = CountLessThan::new(nxt, std::usize::MAX);
    let duration = SystemTime::now().duration_since(start).unwrap();
    debug!("{:?}", duration); // DEBUG

    let start = SystemTime::now();
    for _ in 0..q {
        parse!(it, l: u1, r: u1);
        let c = cs.get(l, r + 1, r);
        writeln!(out, "{}", r + 1 - l - c).unwrap();
    }

    let duration = SystemTime::now().duration_since(start).unwrap();
    debug!("{:?}", duration); // DEBUG
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}