import sys

input = sys.stdin.readline

def main():

    N = int(eval(input()))

    S = list(input().rstrip())



    c = lambda x: ord(x) - ord('a')

    tree = [SegmentTree(N, lambda x,y:x|y) for _ in range(26)]

    for i, l in enumerate(S):

        tree[c(l)].update(i, 1)



    Q = int(eval(input()))

    for _ in range(Q):

        t, a, b = input().rstrip().split()

        if t == '1':

            a = int(a) - 1

            tree[c(S[a])].update(a, 0)

            tree[c(b)].update(a, 1)

            S[a] = b

        else:

            a, b = int(a)-1, int(b)-1

            ans = 0

            for i in range(26):

                t = tree[i].query(a, b+1)

                ans += 1 if t else 0

            print(ans)



class SegmentTree:

    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):

        assert(n, initial_values)

        size = n if n else len(initial_values)

        self.__f, self.__z, self.__c = f, zero_factory, converter

        self.__n = 1 << ((size - 1).bit_length())

        self.__dat = [zero_factory() for _ in range(2 * self.__n)]

        if initial_values:

            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



if __name__ == '__main__':

    main()

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()

import sys

input = sys.stdin.readline


def main():
    N = int(eval(input()))
    S = list(input().rstrip())
    c = lambda x: ord(x) - ord("a")
    tree = [SegmentTree(N, lambda x, y: x | y) for _ in range(26)]
    for i, l in enumerate(S):
        tree[c(l)].update(i, 1)
    Q = int(eval(input()))
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == "1":
            a = int(a) - 1
            tree[c(S[a])].update(a, 0)
            tree[c(b)].update(a, 1)
            S[a] = b
        else:
            a, b = int(a) - 1, int(b) - 1
            ans = 0
            for i in range(26):
                t = tree[i].query(a, b + 1)
                ans += 1 if t else 0
            print(ans)


class SegmentTree:
    def __init__(
        self,
        n=None,
        f=max,
        zero_factory=int,
        converter=lambda x: x,
        initial_values=None,
    ):
        assert (n, initial_values)
        size = n if n else len(initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        self.__n = 1 << ((size - 1).bit_length())
        self.__dat = [zero_factory() for _ in range(2 * self.__n)]
        if initial_values:
            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


if __name__ == "__main__":
    main()

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()

-    S = list(input().rstrip()) +    S = ["$"] + list(input().rstrip()) -    tree = [SegmentTree(N, lambda x, y: x | y) for _ in range(26)] +    bit = [BinaryIndexedTree(N) for _ in range(26)] -        tree[c(l)].update(i, 1) +        if i == 0: +            continue +        bit[c(l)].add(i, 1) -            a = int(a) - 1 -            tree[c(S[a])].update(a, 0) -            tree[c(b)].update(a, 1) +            a = int(a) +            bit[c(S[a])].add(a, -1) +            bit[c(b)].add(a, 1) -            a, b = int(a) - 1, int(b) - 1 +            a, b = int(a), int(b) -                t = tree[i].query(a, b + 1) +                t = bit[i].sum(b) +                if a >= 1: +                    t -= bit[i].sum(a - 1) -class SegmentTree: -    def __init__( -        self, -        n=None, -        f=max, -        zero_factory=int, -        converter=lambda x: x, -        initial_values=None, -    ): -        assert (n, initial_values) -        size = n if n else len(initial_values) -        self.__f, self.__z, self.__c = f, zero_factory, converter -        self.__n = 1 << ((size - 1).bit_length()) -        self.__dat = [zero_factory() for _ in range(2 * self.__n)] +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) -            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)) +            for i in range(1, self.__n + 1): +                self.add(i, initial_values[i - 1])  # slow -    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 add(self, i, v): +        while i <= self.__n: +            self.__dat[i] = self.__f(self.__dat[i], v) +            i += -i & 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: +    def sum(self, r): +        ans = self.__z +        while r: +            r -= -r & r - -    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