Problem:
Score : 500 points

Problem Statement

You are given a string S of length N consisting of lowercase English letters.

Process Q queries of the following two types:

Type 1: change the i_q-th character of S to c_q. (Do nothing if the i_q-th character is already c_q.)

Type 2: answer the number of different characters occurring in the substring of S between the l_q-th and r_q-th characters (inclusive).

Constraints

N, Q, i_q, l_q, and r_q are integers.

S is a string consisting of lowercase English letters.

c_q is a lowercase English letter.

1 \leq N \leq 500000

1 \leq Q \leq 20000

|S| = N

1 \leq i_q \leq N

1 \leq l_q \leq r_q \leq N

There is at least one query of type 2 in each testcase.

Input

Input is given from Standard Input in the following format:

N
S
Q
Query_1
\vdots
Query_Q

Here, Query_i in the 4-th through (Q+3)-th lines is one of the following:

1 i_q c_q

2 l_q r_q

Output

For each query of type 2, print a line containing the answer.

Sample Input 1

7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7

Sample Output 1

3
1
5

In the first query, cdbb contains three kinds of letters: b , c , and d, so we print 3.

In the second query, S is modified to abcdzbd.

In the third query, a contains one kind of letter: a, so we print 1.

In the fourth query, S is modified to abcazbd.

In the fifth query, S does not change and is still abcazbd.

In the sixth query, abcazbd contains five kinds of letters: a, b, c, d, and z, so we print 5.

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[macro_use]
mod input_mcr {
    // ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
    // diff: using Parser
    #[macro_export(local_inner_macros)]
    macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

    #[macro_export(local_inner_macros)]
    macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

    #[macro_export(local_inner_macros)]
    macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, char_) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()[0]
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, i64_) => {
        $parser.fast_i64()
    };
    ($parser:ident, usize_) => {
        $parser.fast_i64() as usize
    };
    ($parser:ident, usize1_) => {
        ($parser.fast_i64() - 1) as usize
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

    use std::io;
    use std::io::BufRead;
    use std::str;

    // ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
    // ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
    // diff: using std::io::BufRead::fill_buf()
    pub struct Parser<R> {
        pub reader: R,
        buf: Vec<u8>,
        pos: usize,
    }

    impl Parser<io::Empty> {
        pub fn from_str(s: &str) -> Parser<io::Empty> {
            Parser {
                reader: io::empty(),
                buf: s.as_bytes().to_vec(),
                pos: 0,
            }
        }
    }

    impl<R: BufRead> Parser<R> {
        pub fn new(reader: R) -> Parser<R> {
            Parser {
                reader: reader,
                buf: vec![],
                pos: 0,
            }
        }
        pub fn update_buf(&mut self) {
            self.buf.clear();
            self.pos = 0;
            loop {
                let (len, complete) = {
                    let buf2 = self.reader.fill_buf().unwrap();
                    self.buf.extend_from_slice(buf2);
                    let len = buf2.len();
                    (len, buf2[len - 1] <= 0x20)
                };
                self.reader.consume(len);
                if complete {
                    break;
                }
            }
        }
        pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
            loop {
                let mut begin = self.pos;
                while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                    begin += 1;
                }
                let mut end = begin;
                while end < self.buf.len() && (self.buf[end] > 0x20) {
                    end += 1;
                }
                if begin != self.buf.len() {
                    self.pos = end;
                    return unsafe { str::from_utf8_unchecked(&self.buf[begin..end]) }.parse::<T>();
                } else {
                    self.update_buf();
                }
            }
        }
        pub fn fast_i64(&mut self) -> i64 {
            loop {
                let mut begin = self.pos;
                while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                    begin += 1;
                }
                if begin == self.buf.len() {
                    self.update_buf();
                    continue;
                }
                let mut res = 0;
                let (is_positive, mut end) = match self.buf[begin] {
                    b'+' => (true, begin + 1),
                    b'-' => (false, begin + 1),
                    _ => (true, begin),
                };
                while end < self.buf.len() && (self.buf[end] > 0x20) {
                    res = res * 10 + (self.buf[end] as i64 - '0' as i64);
                    end += 1;
                }
                if begin != self.buf.len() {
                    self.pos = end;
                    return if is_positive { res } else { -res };
                } else {
                    self.update_buf();
                }
            }
        }
    }
}

mod bit {
    #[derive(Debug, Clone)]
    pub struct BIT {
        xs: Vec<i64>,
        n: usize,
    }

    // 1-indexed !!!
    impl BIT {
        pub fn new(n: usize) -> BIT {
            BIT {
                xs: vec![0; n + 1],
                n: n,
            }
        }
        pub fn sum(&self, i: usize) -> i64 {
            let mut res = 0;
            let mut i = i;
            while i > 0 {
                res += self.xs[i];
                i -= i & !(i - 1);
            }
            res
        }
        pub fn add(&mut self, i: usize, x: i64) {
            let mut i = i;
            while i <= self.n {
                self.xs[i] += x;
                i += i & !(i - 1);
            }
        }
        // return <= i
        pub fn max_non_zero_index(&self, i: usize) -> usize {
            let mut d = 1 << 28;
            let mut i = i;
            while d != 0 {
                if i < d {
                    d /= 2;
                    continue;
                }
                if self.sum(i - d) == self.sum(i) {
                    i = i - d;
                }
                d /= 2;
            }
            i
        }
        pub fn min_non_zero_index(&self, i: usize) -> usize {
            let mut d = 1 << 28;
            let mut i = i;
            while d != 0 {
                if i + d > self.n {
                    d /= 2;
                    continue;
                }
                if self.sum(i + d) == self.sum(i) {
                    i = i + d;
                }
                d /= 2;
            }
            i + 1
        }
    }

    #[test]
    fn test_bit_1() {
        let mut bit = BIT::new(6);
        bit.add(1, 1);
        bit.add(2, 1);
        bit.add(4, 1);
        assert_eq!(bit.max_non_zero_index(1), 1);
        assert_eq!(bit.max_non_zero_index(2), 2);
        assert_eq!(bit.max_non_zero_index(3), 2);
        assert_eq!(bit.max_non_zero_index(4), 4);
        assert_eq!(bit.max_non_zero_index(5), 4);
        assert_eq!(bit.max_non_zero_index(6), 4);
    }
}

use input_mcr::*;
use std::cmp::*;

use bit::*;

fn main() {
    input! {
        new_stdin_parser = parser,
        n: usize,
        s: chars,
        q: usize,
    }
    let mut s = s;
    let mut bits = vec![BIT::new(n.next_power_of_two()); 26];
    for (i, &c) in s.iter().enumerate() {
        let v = c as usize - 'a' as usize;
        bits[v].add(i + 1, 1);
    }
    for _ in 0..q {
        input! {
            parser = parser,
            t: usize,
        }
        if t == 1 {
            input! {
                parser = parser,
                i: usize,
                c: char_,
            }
            let v1 = s[i - 1] as usize - 'a' as usize;
            let v2 = c as usize - 'a' as usize;
            bits[v1].add(i, -1);
            bits[v2].add(i, 1);
            s[i - 1] = c;
        } else {
            input! {
                parser = parser,
                l: usize,
                r: usize,
            }
            let mut res = 0;
            for v in 0..26 {
                if bits[v].sum(r) - bits[v].sum(l - 1) != 0 {
                    res += 1;
                }
            }
            println!("{}", res);
        }
    }
}