### BUGGY CODE ###

import bisect, collections, copy, heapq, itertools, math, string
import sys
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int, sys.stdin.readline().rstrip().split())
def LI(): return list(map(int, sys.stdin.readline().rstrip().split()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())

from  collections import defaultdict
import bisect
def main():
    N = I()
    S_ = S()
    Q = I()
    D = {'a': [], 'b': [], 'c': [], 'd': [], 'e': [], 'f': [], 'g': [], 'h': [], 'i': [], 'j': [], 'k': [], 'l': [], 'm': [], 'n': [], 'o': [], 'p': [], 'q': [], 'r': [], 's': [], 't': [], 'u': [], 'v': [], 'w': [], 'x': [], 'y': [], 'z': []}

    for i in range(N):
        D[S_[i]].append(i)
    for i in range(Q):
        query = LS()
        if query[0] == '1':
            i_q = int(query[1])
            c_q = query[2]
            s_q = S_[i_q - 1]
            if s_q != c_q:
                S_ = S_[:i_q - 1] + c_q + S_[i_q:]
                D[c_q].append(i_q - 1)
                D[c_q].sort()
                D[s_q].remove(i_q - 1)
        if query[0] == '2':
            cnt = 0
            l_q = int(query[1]) - 1
            r_q = int(query[2]) - 1
            for value in D.values():
                l_i = bisect.bisect_left(value, l_q)
                r_i = bisect.bisect_right(value, r_q)
                if l_i != r_i:
                    cnt += 1
            print(cnt)

if __name__ == "__main__":
    main()

### FIXED CODE ###

import bisect, collections, copy, heapq, itertools, math, string
import sys
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int, sys.stdin.readline().rstrip().split())
def LI(): return list(map(int, sys.stdin.readline().rstrip().split()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())

from  collections import defaultdict
import bisect


# SegTreeの関数
def segfunc(x, y):
    return x | y


# 単位元
# min->inf, max->-inf, add->0, mul->1
ide_ele = set()


# セグメント木
class SegTree:
    """
    init(init_val, segfunc, ide_ele): 配列init_valで初期化、構築
    update(k, x): k番目の値をxに更新
    query(l, r): 区間[l, r)をsegfuncしたものを返す
    """

    def __init__(self, init_val, segfunc, ide_ele):
        n = len(init_val)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        self.num = 1 << (n - 1).bit_length()
        self.tree = [ide_ele] * 2 * self.num
        # 配列の値を葉にセットする
        for i in range(n):
            self.tree[self.num + i] = init_val[i]
        # 構築
        for i in range(self.num - 1, 0, -1):
            self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

    def update(self, k, x):
        """
        k番目の値をxに更新
        :param k: index(0-index)
        :param x: update value
        """
        k += self.num
        self.tree[k] = x
        while k > 1:
            self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
            k >>= 1

    def query(self, l, r):
        """
        [l, r)のsegfuncしたものを得る
        :param l: 0-index
        :param r: 0-index
        :return:
        """
        res = self.ide_ele
        l += self.num
        r += self.num
        while l < r:
            if l & 1:
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1:
                res = self.segfunc(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res

def main():
    N = I()
    S_ = S()
    S_list = []
    Q = I()
    for s in S_:
        val = set()
        val.add(s)
        S_list.append(val)


    segtree = SegTree(S_list, segfunc, ide_ele)
    for i in range(Q):
        query = LS()
        if query[0] == '1':
            i_q = int(query[1]) - 1
            c_q = query[2]
            segtree.update(i_q, {c_q})
        if query[0] == '2':
            l_q = int(query[1]) - 1
            r_q = int(query[2])
            ans = len(segtree.query(l_q, r_q))
            print(ans)

if __name__ == "__main__":
    main()