# Original solution
import sys
input = sys.stdin.readline
def main():
    N = int(eval(input()))
    S = ['$'] + list(input().rstrip())

    c = lambda x: ord(x) - ord('a')
    bit = [BinaryIndexedTree(N) for _ in range(26)]
    for i, l in enumerate(S):
        if i == 0: continue
        bit[c(l)].add(i, 1)

    Q = int(eval(input()))
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1':
            a = int(a)
            bit[c(S[a])].add(a, -1)
            bit[c(b)].add(a, 1)
            S[a] = b
        else:
            a, b = int(a), int(b)
            ans = 0
            for i in range(26):
                t = bit[i].sum(b)
                if a >= 1: t -= bit[i].sum(a-1)
                ans += 1 if t else 0
            print(ans)

class BinaryIndexedTree:
    def __init__(self, n=None, f=lambda x,y:x+y, zero=0, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, = f, zero
        self.__n = n if n else len(initial_values)
        self.__dat = [zero] * (self.__n + 1)
        if initial_values:
            for i in range(1, self.__n + 1): self.add(i, initial_values[i-1]) #slow

    def add(self, i, v):
        while i <= self.__n:
            self.__dat[i] = self.__f(self.__dat[i], v)
            i += -i&i

    def sum(self, r):
        ans = self.__z
        while r:
            ans = self.__f(ans, self.__dat[r])
            r -= -r&r
        return ans

if __name__ == '__main__':
    main()


# Optimized solution
class SegmentTree:
    def __init__(self, initial_values, f=max, zero=0, converter=lambda x:x):
        self.__f, self.__z, self.__c, self.__size = f, zero, converter, len(initial_values)
        self.__n = 1 << ((self.__size - 1).bit_length())
        self.__dat = [zero] * (2 * self.__n)
        zi = self.__get_leaf(0)
        for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
        for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))
    
    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))
    
    def query(self, from_inclusive, to_exclusive):
        ans = self.__z
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

import sys
input = sys.stdin.readline
N = int(eval(input()))
S = input().rstrip()
tree = SegmentTree(S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
Q = int(eval(input()))
update = tree.update
query = tree.query
for _ in range(Q):
    t, a, b = input().rstrip().split()
    if t == '1': update(int(a)-1, b)
    else: print((bin(query(int(a)-1, int(b))).count('1')))