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.42.0) (judge verdict: Wrong Answer)

#![allow(unused_imports)]

// language: Rust(1.42.0)
// check available crates on AtCoder at "https://atcoder.jp/contests/language-test-202001"
// My Library Repositry is at "https://github.com/Loptall/sfcpl"

/*
    青perfほしいよ〜！
*/

// from std...
use std::cmp::{
    max, min, Ordering,
    Ordering::{Equal, Greater, Less},
    Reverse,
};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::convert::TryInto;
use std::fmt;
use std::mem::swap;
use std::num::{NonZeroU32, ParseIntError};
use std::ops::{
    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
    Index, IndexMut, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
    SubAssign,
};
use std::process::exit;
use std::{f32, f64, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

// Dep' crates are...
use itertools::*;
use itertools_num::*;
use lazy_static::lazy_static;
use maplit::{btreemap, btreeset, hashmap, hashset};
use num_bigint::{BigInt, BigUint};
use num_complex::Complex;
use num_integer::{binomial, gcd, lcm, multinomial, Integer};
use num_rational::Rational;
use num_traits::{
    clamp, one, pow, zero, Num, NumAssignOps, NumOps, One, Pow, Signed, Unsigned, Zero,
};
use permutohedron::Heap;
use proconio::{
    derive_readable, fastout, input, is_stdin_empty,
    marker::{Bytes, Chars, Isize1, Usize1},
};
use rand::random;

pub trait Visualize {
    fn visualize(&self, split: &str);
    fn continuous(&self) {
        self.visualize("");
    }
    fn spaces(&self) {
        self.visualize(" ");
    }
    fn lines(&self) {
        self.visualize("\n");
    }
}
macro_rules! impl_vis_for_sized {
    ($($t:ty),+) => {
        $(
            impl Visualize for $t {
                fn visualize(&self, _split: &str) {
                    print!("{}", self);
                }
            }
        )+
    };
}
impl_vis_for_sized! {
    usize, u8, u16, u32, u64, u128,
    isize, i8, i16, i32, i64, i128,
    f64, f32,
    String, &str, char
}
impl<T: fmt::Display> Visualize for [T] {
    fn visualize(&self, split: &str) {
        print!("{}", self.iter().join(split));
    }
}
#[macro_export]
macro_rules! vis {
    // end
    () => {
        println!();
    };

    // last element + trailing pattern
    ($last:expr ;) => {
        $last.lines();
        vis!()
    };
    ($last:expr =>) => {
        $last.continuous();
        vis!();
    };
    ($last:expr $(,)?) => {
        $last.spaces();
        vis!();
    };

    // get first element and pass rest
    ($first:expr; $($rest:tt)*) => {
        $first.lines();
        println!();
        vis!($($rest)*);
    };
    ($first:expr => $($rest:tt)*) => {
        $first.continuous();
        vis!($($rest)*);
    };
    ($first:expr, $($rest:tt)*) => {
        $first.spaces();
        print!(" ");
        vis!($($rest)*);
    };
}
pub const MOD10E9_7: usize = 1000000007; // 10 ^ 9 + 7
pub const MOD99_: usize = 998244353;
pub const MAX: usize = std::usize::MAX; // = 2 ^ 64 - 1 = 18446744073709551615 ≈ 1.8 * 10 ^ 19
pub const INF: usize = 2000000000000000000; // MAX / 9 < 2 * 10e18 < MAX / 10
pub const FNI: i64 = -2000000000000000000; // == -(INF as i64)
pub const PI: f64 = f64::consts::PI; // 3.141592653589793 -- 10 ^ -15
pub const ASCII_A_LARGE: u8 = 65;
pub const ASCII_A_SMALL: u8 = 97;
pub const ASCII_0: u8 = 48;
pub const ADJ4: &[(isize, isize); 4] = &[(1, 0), (0, 1), (-1, 0), (0, -1)];
pub const ADJ8: &[(isize, isize); 8] = &[
    (1, 0),
    (1, 1),
    (0, 1),
    (-1, 1),
    (-1, 0),
    (-1, -1),
    (0, -1),
    (1, -1),
];

/// 単位元が定義される `T -> T -> T`型の演算
pub trait Monoid: Sized + PartialEq {
    fn identity() -> Self;
    fn op(x: &Self, y: &Self) -> Self;
    fn fold(v: &[Self]) -> Self {
        v.iter().fold(Self::identity(), |a, b| Self::op(&a, b))
    }
}
/// Monoidトレイトの自動実装マクロ
/// 一行目にモノイド名、
/// 二行目に単位元
/// 三行目に`2引数を取って、同型の演算結果を返すクロージャを渡す
/// ```example
/// monoid_def! {
///     Max<usize>,
///     std::usize::MIN,
///     |x: usize, y: usize| x.max(y)
/// }
/// ```
#[macro_export]
macro_rules ! monoid_def {{$ M : ident <$ t : ty >, $ id : expr , $ me : expr } => {# [derive (Debug , Clone , Copy , PartialEq ) ] pub struct $ M ($ t ) ; impl Monoid for $ M {fn identity () -> Self {$ M ($ id ) } fn op (x : & Self , y : & Self ) -> Self {let f = $ me ; $ M (f (x . 0 , y . 0 ) ) } } impl Into <$ M > for $ t {fn into (self ) -> $ M {$ M (self ) } } } ; }

#[derive(Clone)]
pub struct DelayedSegmentTree<'a, T: Monoid, E: Monoid> {
    /// length of tree's leaves
    len: usize,
    /// length of whole vec
    size: usize,
    effect: &'a dyn Fn(T, E) -> T,
    segment: Vec<T>,
    lazy: Vec<E>,
}
fn childrens_idx(n: usize) -> (usize, usize) {
    (n * 2 + 1, n * 2 + 2)
}
impl<'a, T: Monoid + Clone + Copy, E: Monoid + Clone + Copy> DelayedSegmentTree<'a, T, E> {
    pub fn new<I: Into<T> + Copy>(v: &[I], effect: &'a dyn Fn(T, E) -> T) -> Self {
        let n = v.len();
        let len = n.next_power_of_two();
        let size = 2 * len - 1;
        let mut segment = vec![T::identity(); size];
        let lazy = vec![E::identity(); size];
        for i in (0..size).rev() {
            if i >= len - 1 {
                if i + 1 - len < n {
                    segment[i] = (v[i + 1 - len]).into();
                } else {
                    continue;
                }
            } else {
                let (left, right) = childrens_idx(i);
                segment[i] = T::op(&segment[left], &segment[right]);
            }
        }
        Self {
            len,
            size,
            effect,
            segment,
            lazy,
        }
    }
    /// number of LEAVES in tree
    pub fn len(&self) -> usize {
        self.len
    }
    /// length of vector
    pub fn size(&self) -> usize {
        self.size
    }
    /// `i`番目の葉の参照をとる
    pub fn get(&self, i: usize) -> Option<&T> {
        self.segment.get(self.size - self.len + i)
    }
    /// `i`番目の葉の可変参照をとる
    /// # Unsafe
    /// 葉の部分は変更されうるけれど、その親要素へ変更が伝達されない
    /// update()を使うこと
    pub unsafe fn get_mut(&mut self, i: usize) -> Option<&mut T> {
        let size = self.size();
        let len = self.len();
        self.segment.get_mut(size - len + i)
    }
    fn eval(&mut self, i: usize) {
        if self.lazy[i] == E::identity() {
            return;
        }
        if i < self.len() - 1 {
            let (left, right) = childrens_idx(i);
            self.lazy[left] = E::op(&self.lazy[left], &self.lazy[i]);
            self.lazy[right] = E::op(&self.lazy[right], &self.lazy[i]);
        }
        let f = self.effect;
        self.segment[i] = f(self.segment[i], self.lazy[i]);
        self.lazy[i] = E::identity();
    }
    pub fn update_range(&mut self, from: usize, to: usize, x: E) {
        self.update_range_inner(from, to, 0, self.len(), 0, x);
    }
    fn update_range_inner(
        &mut self,
        from: usize,
        to: usize,
        l_bound: usize,
        r_bound: usize,
        k: usize,
        x: E,
    ) {
        self.eval(k);
        if from >= r_bound || to <= l_bound {
            return;
        }
        if from <= l_bound && to >= r_bound {
            self.lazy[k] = E::op(&self.lazy[k], &x);
            self.eval(k);
            return;
        }
        let sep = (l_bound + r_bound) / 2;
        let (left, right) = childrens_idx(k);
        self.update_range_inner(from, to, l_bound, sep, left, x);
        self.update_range_inner(from, to, sep, r_bound, right, x);
        self.segment[k] = T::op(&self.segment[left], &self.segment[right]);
    }
    /// 区間、`[from..to)`を指定の`Monoid`でfoldした演算結果
    pub fn range(&mut self, from: usize, to: usize) -> T {
        self.range_inner(from, to, 0, self.len(), 0)
    }
    fn range_inner(
        &mut self,
        from: usize,
        to: usize,
        l_bound: usize,
        r_bound: usize,
        k: usize,
    ) -> T {
        self.eval(k);
        if from <= l_bound && to >= r_bound {
            self.segment[k]
        } else if from >= r_bound || to <= l_bound {
            T::identity()
        } else {
            let sep = (l_bound + r_bound) / 2;
            T::op(
                &self.range_inner(from, to, l_bound, sep, 2 * k + 1),
                &self.range_inner(from, to, sep, r_bound, 2 * k + 2),
            )
        }
    }
}

monoid_def! {
    Or<usize>,
    0,
    |x, y| x | y
}

monoid_def! {
    Ch<char>,
    ' ',
    |x, y| if x == ' ' || y == ' ' { x } else { y }
}

// code...
// #[fastout]
fn main() {
    input! {
        n: usize,
        s: Chars,
        q: usize,
    }

    let ef = |a: Or, b: Ch| if b.0 == ' ' { Or(0) } else { char_to_bits(b) };
    let mut sg = DelayedSegmentTree::<Or, Ch>::new(
        &s.iter().map(|x| char_to_bits(Ch(*x)).0).collect::<Vec<_>>(),
        &ef,
    );

    for _ in 0..q {
        input! {
            w: u8,
        }

        if w == 1 {
            input! {
                i: usize, c: char
            }

            sg.update_range(i, i + 1, Ch(c));
        } else {
            input! {
                l: Usize1, r: usize
            }

            let ans = sg.range(l, r).0.count_ones();
            vis!(ans);
        }
    }
}

fn char_to_bits(c: Ch) -> Or {
    let sh = (c.0 as u8 - ASCII_A_SMALL) as usize;
    Or(1 << sh)
}