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)

mod persistent_segment_tree {
    use std::rc::*;
    pub trait BinaryOperation {
        type T: Clone;
        fn fold(l: Self::T, r: Self::T) -> Self::T;
        fn e() -> Self::T;
    }
    type Link<R> = Option<Rc<Node<R>>>;
    struct Node<R: BinaryOperation> {
        val: R::T,
        left: Link<R>,
        right: Link<R>,
    }
    impl<R: BinaryOperation> Node<R> {
        fn new_node(left: Link<R>, right: Link<R>) -> Link<R> {
            Some(Rc::new(Node {
                val: R::fold(Node::get_val(&left), Node::get_val(&right)),
                left: left,
                right: right,
            }))
        }
        fn get_val(node: &Link<R>) -> R::T {
            node.as_ref().map_or(R::e(), |t| t.val.clone())
        }
        fn find(node: &Link<R>, l: usize, r: usize, x: usize, y: usize) -> R::T {
            if node.is_none() || y <= l || r <= x {
                return R::e();
            }
            let node = node.as_ref().unwrap();
            if x <= l && r <= y {
                node.val.clone()
            } else {
                let m = (l + r) / 2;
                R::fold(Node::find(&node.left, l, m, x, y), Node::find(&node.right, m, r, x, y))
            }
        }
        fn update(node: &Link<R>, l: usize, r: usize, x: usize, val: R::T) -> Link<R> {
            if l + 1 == r {
                return Some(Rc::new(Node {
                    val: val,
                    left: None,
                    right: None,
                }));
            }
            let mut left = None;
            let mut right = None;
            if let Some(node) = node.as_ref() {
                left = node.left.clone();
                right = node.right.clone();
            }
            let m = (l + r) / 2;
            if x < m {
                left = Node::update(&left, l, m, x, val);
            } else {
                right = Node::update(&right, m, r, x, val);
            }
            Node::new_node(left, right)
        }
    }
    pub struct PURQ<R: BinaryOperation> {
        root: Link<R>,
        left: usize,
        right: usize,
    }
    impl<R: BinaryOperation> std::clone::Clone for PURQ<R> {
        fn clone(&self) -> Self {
            PURQ {
                root: self.root.clone(),
                left: self.left,
                right: self.right,
            }
        }
    }
    impl<R: BinaryOperation> PURQ<R> {
        pub fn new(left: usize, right: usize) -> Self {
            PURQ {
                root: None,
                left: left,
                right: right,
            }
        }
        pub fn update(&self, x: usize, val: R::T) -> Self {
            assert!(self.left <= x && x < self.right);
            PURQ {
                root: Node::update(&self.root, self.left, self.right, x, val),
                left: self.left,
                right: self.right,
            }
        }
        pub fn find(&self, l: usize, r: usize) -> R::T {
            assert!(self.left <= l && l < r && r <= self.right);
            Node::find(&self.root, self.left, self.right, l, r)
        }
    }
}

use proconio::*;
use proconio::marker::*;

use persistent_segment_tree::*;

struct SUM;
impl BinaryOperation for SUM {
    type T = u32;
    fn fold(l: Self::T, r: Self::T) -> Self::T {
        l + r
    }
    fn e() -> Self::T {
        0
    }
}

#[fastout]
fn run() {
    input! {
        n: usize,
        q: usize,
        c: [Usize1; n],
        ask: [(Usize1, usize); q],
    }
    let mut a = vec![vec![]; n];
    for (i, &c) in c.iter().enumerate() {
        a[c].push(i);
    }
    let mut seg = PURQ::<SUM>::new(0, n);
    for a in a.iter_mut() {
        a.reverse();
        if let Some(k) = a.pop() {
            seg = seg.update(k, 1);
        }
    }
    let mut memo = vec![];
    for &c in c.iter() {
        memo.push(seg.clone());
        if let Some(k) = a[c].pop() {
            seg = seg.update(k, 1);
        }
    }
    for (l, r) in ask {
        println!("{}", memo[l].find(l, r));
    }
}

fn main() {
    run();
}