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

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

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

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

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