# Original solution
import sys
input = sys.stdin.readline


class Bit:
    def __init__(self, n):
        self.n = n
        self.tree = [0]*(n+1)
        self.el = [0]*(n+1)
        self.depth = n.bit_length() - 1

    def sum(self, i):
        """ 区間[0,i) の総和を求める """
        s = 0
        i -= 1
        while i >= 0:
            s += self.tree[i]
            i = (i & (i + 1) )- 1
        return s

    def add(self, i, x):
        """ i 番目の要素に x を足す """
        self.el[i] += x
        while i < self.n:
            self.tree[i] += x
            i |= i + 1

    def get(self, i, j=None):
        """ 部分区間和 [i, j) """
        if j is None:
            return self.el[i]
        if i == 0:
            return self.sum(j)
        return self.sum(j) - self.sum(i)

    def lower_bound(self, x, equal=False):
        """ (a0+a1+...+ai < x となる最大の i, その時の a0+a1+...+ai )
             a0+a1+...+ai <= x としたい場合は equal = True
             二分探索であるため、ai>=0 を満たす必要がある"""
        sum_ = 0
        pos = -1    # 1-indexed の時は pos = 0
        if not equal:
            for i in range(self.depth, -1, -1):
                k = pos + (1 << i)
                if k < self.n and sum_ + self.tree[k] < x:  # 1-indexed の時は k <= self.n
                    sum_ += self.tree[k]
                    pos += 1 << i
        if equal:
            for i in range(self.depth, -1, -1):
                k = pos + (1 << i)
                if k < self.n and sum_ + self.tree[k] <= x: # 1-indexed の時は k <= self.n
                    sum_ += self.tree[k]
                    pos += 1 << i
        return pos, sum_

    def __getitem__(self, s):
        """ [a0, a1, a2, ...] """
        return self.el[s]

    def __iter__(self):
        """ [a0, a1, a2, ...] """
        for s in self.el[:self.n]:
            yield s

    def __str__(self):
        text1 = " ".join(["element:            "] + list(map(str, self)))
        text2 = " ".join(["cumsum(1-indexed):  "] + list(str(self.sum(i)) for i in range(1, self.n + 1)))
        return "\n".join((text1, text2))

####################################################################################################

import string

N = int(eval(input()))
S = input().strip()
Q = int(eval(input()))

B = [Bit(N) for _ in range(26)]

abc = string.ascii_lowercase                                            # [a-z] をロード
abc2 = dict()
for i, s in enumerate(abc):
    abc2[s] = i

for i, s in enumerate(S):
    B[abc2[s]].add(i,1)

for _ in range(Q):
    q = list(input().split())
    if q[0] == "1":
        a = int(q[1]) - 1
        b = q[2]
        for i in range(26):
            if B[i].el[a] == 1:
                B[i].add(a,-1)
        B[abc2[b]].add(a,1)
    if q[0] == "2":
        a = int(q[1]) - 1
        b = int(q[2]) - 1
        res = 0
        for i in range(26):
            res += (B[i].get(a, b+1) > 0)
        print(res)


# Optimized solution
# https://atcoder.jp/contests/abc157/tasks/abc157_e

import sys
input = sys.stdin.readline


class SegmentTree:

    def __init__(self, n, op, e):
        """
        :param n: 要素数
        :param op: 二項演算
        :param e: 単位減
        例) 区間最小値  SegmentTree(n, lambda a, b : a if a < b else b, 10 ** 18)
            区間和     SegmentTree(n, lambda a, b : a + b, 0)
        """
        self.n = n
        self.op = op
        self.e = e
        self.size = 1 << (self.n - 1).bit_length()      # st[self.size + i] = array[i]
        self.tree = [self.e] * (self.size << 1)

    def built(self, array):
        """arrayを初期値とするセグメント木を構築"""
        for i in range(self.n):
            self.tree[self.size + i] = array[i]
        for i in range(self.size - 1, 0, -1):
            self.tree[i] = self.op(self.tree[i << 1], self.tree[(i << 1) + 1])

    def update(self, i, x):
        """i 番目の要素を x に更新"""
        i += self.size
        self.tree[i] = x
        while i > 1:
            i >>= 1
            self.tree[i] = self.op(self.tree[i << 1], self.tree[(i << 1) + 1])

    def get_val(self, l, r):
        """[l, r)の畳み込みの結果を返す"""
        l, r = l + self.size, r + self.size
        res = self.e
        while l < r:
            if l & 1:
                res = self.op(self.tree[l], res)
                l += 1
            if r & 1:
                r -= 1
                res = self.op(self.tree[r], res)
            l, r = l >> 1, r >> 1
        return res


##################################################################################################################

def popcount(x):
    return bin(x).count("1")

N = int(eval(input()))
st = SegmentTree(N, lambda a, b: a | b, 0)
S = input().strip()
data = []
for s in S:
    data.append(1 << (ord(s) - ord("a")))
st.built(data)
Q = int(eval(input()))
for _ in range(Q):
    q, a, b = input().split()
    if q == "1":
        st.update(int(a)-1, 1 << (ord(b) - ord("a")))
    if q == "2":
        a = int(a) - 1
        b = int(b)
        print((popcount(st.get_val(a, b))))