use std::io::*;
use std::str::FromStr;

pub fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

pub fn read_n<T: FromStr>(n: usize) -> Vec<T> {
    read_n_logic::<T>(n, vec![])
}

pub fn read_n_logic<T: FromStr>(n: usize, mut a: Vec<T>) -> Vec<T> {
    match n {
        0 => a,
        _ => {
            a.push(read::<T>());
            read_n_logic(n - 1, a)
        }
    }
}
use std::cmp::{max, min};

struct SegTree {
    pub v: Vec<i64>,
    next_two: usize,
}

impl SegTree {
    fn new(org: Vec<i64>) -> Self {
        let orglen = org.len();
        let mut next_two = 1;
        while next_two < orglen {
            next_two *= 2;
        }

        let vlen = next_two * 2;
        let mut v: Vec<i64> = vec![0; vlen];

        for i in (0..vlen).rev() {
            if next_two <= i && i - next_two < orglen {
                v[i] = org[i - next_two];
            }
            if i != 0 && i < next_two {
                v[i] = v[i * 2] | v[i * 2 + 1];
            }
        }
        SegTree {
            v: v,
            next_two: next_two,
        }
    }
    fn update(&mut self, idx: usize, nv: i64) {
        self.v[idx + self.next_two - 1] = nv;
        let mut current_idx = idx + self.next_two - 1;
        while current_idx != 1 {
            current_idx = current_idx / 2;
            self.v[current_idx] = self.v[current_idx * 2] | self.v[current_idx * 2 + 1];
        }
    }

    fn find(&self, a: usize, b: usize, l: usize, r: usize, k: usize) -> i64 {
        // println!("a:{}, b: {}, l: {}, r: {}, k: {}", a, b, l, r, k);
        if r < a || b < l {
            return 0;
        }

        if l == r {
            return self.v[l];
        }

        if a <= l && r <= b {
            return self.v[k];
        }

        let vl = self.find(a, b, l, (l + r - 1) / 2, k * 2);
        let vr = self.find(a, b, (l + r + 1) / 2, r, k * 2 + 1);
        return vl | vr;
    }
}

// ref: https://atcoder.jp/contests/abc157/submissions/10556514
fn main() {
    let n: usize = read();
    let s: String = read();
    let sc: Vec<char> = s.chars().collect();
    let sn: Vec<_> = sc
        .into_iter()
        .map(|c| 1 << (c as i32 - 'a' as i32))
        .collect();
    let mut st: SegTree = SegTree::new(sn);
    let q: usize = read();
    let mut next_two = 1;
    while next_two < n {
        next_two *= 2;
    }

    let mut anss = vec![];

    for _ in 0..q {
        let ty: usize = read();
        if ty == 1 {
            let i: usize = read();
            let s: String = read();
            let c: char = s.chars().collect::<Vec<char>>()[0];
            let cn: i64 = 1 << c as i64 - 'a' as i64;
            st.update(i, cn);

        } else {
            let i: usize = read();
            let r: usize = read();
            let mut ans = st.find(
                i + next_two - 1,
                r + next_two - 1,
                next_two,
                next_two * 2 - 1,
                1,
            );
            // count 1 in 2 base numbers
            let mut cnt = 0;
            while ans > 0 {
                if ans % 2 == 1 {
                    cnt += 1;
                }
                ans = ans / 2;
            }
            anss.push(cnt);
        }
    }

    for i in 0..anss.len() {
        let ai = anss[i];
        println!("{}", ai);
    }
}


Measured memory_bytes: 18672