#!/usr/bin/env python3

import sys

DEBUG = False


class SegmentTree:

    # Use 1-based index internally
    def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
    def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
    def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc

def read(t = str):
    return t(sys.stdin.readline().rstrip())

def read_list(t = str, sep = " "):
    return [t(s) for s in sys.stdin.readline().rstrip().split(sep)]

def dprint(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)
    return


def main():
    read()
    s = read()

    a_ord = ord("a")
    bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)}

    apps = SegmentTree(len(s), lambda x, y: x | y, 0)
    i = 0
    for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

    nr_q = read(int)
    for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges


if __name__ == "__main__":
    main() import sys sys DEBUG = False DEBUG False class SegmentTree:

    # Use 1-based index internally
    def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
    def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
    def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc SegmentTree def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
     __init__ self.n = 1 self.n self n 1 while self.n < n:
            self.n *= 2
         self.n < n self.n self n n self.n *= 2 self.n self n 2 self.nodes = [fillval] * (self.n * 2 - 1 + 1) self.nodes self nodes [fillval] * (self.n * 2 - 1 + 1) [fillval] fillval self.n * 2 - 1 + 1 self.n * 2 - 1 self.n * 2 self.n self n 2 1 1 self.merge_func = merge_func self.merge_func self merge_func merge_func self.fillval = fillval self.fillval self fillval fillval self self n n merge_func merge_func fillval=sys.maxsize fillval sys.maxsize sys maxsize def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
     update idx += 1 idx 1 nodes = self.nodes nodes self.nodes self nodes mergef = self.merge_func mergef self.merge_func self merge_func idx += self.n - 1 idx self.n - 1 self.n self n 1 nodes[idx] = val nodes[idx] nodes idx val while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
     idx > 1 idx 1 idx >>= 1 idx 1 nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) nodes[idx] nodes idx mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) mergef nodes[idx << 1] nodes idx << 1 idx 1 nodes[(idx << 1) + 1] nodes (idx << 1) + 1 idx << 1 idx 1 1 self self idx idx val val def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc query l += 1 l 1 r += 1 r 1 l += self.n - 1 l self.n - 1 self.n self n 1 r += self.n - 1 r self.n - 1 self.n self n 1 acc = self.fillval acc self.fillval self fillval while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
         l < r l r if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
             l & 1 l 1 acc = self.merge_func(acc, self.nodes[l]) acc self.merge_func(acc, self.nodes[l]) self.merge_func self merge_func acc self.nodes[l] self.nodes self nodes l l += 1 l 1 if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
             r & 1 r 1 acc = self.merge_func(acc, self.nodes[r - 1]) acc self.merge_func(acc, self.nodes[r - 1]) self.merge_func self merge_func acc self.nodes[r - 1] self.nodes self nodes r - 1 r 1 r -= 1 r 1 l >>= 1 l 1 r >>= 1 r 1 return acc acc self self l l r r def read(t = str):
    return t(sys.stdin.readline().rstrip()) read return t(sys.stdin.readline().rstrip()) t(sys.stdin.readline().rstrip()) t sys.stdin.readline().rstrip() sys.stdin.readline().rstrip sys.stdin.readline() sys.stdin.readline sys.stdin sys stdin readline rstrip t = str t str def read_list(t = str, sep = " "):
    return [t(s) for s in sys.stdin.readline().rstrip().split(sep)] read_list t(s) for s in sys.stdin.readline().rstrip().split(sep) for s in sys.stdin.readline().rstrip().split(sep) s sys.stdin.readline().rstrip().split(sep) sys.stdin.readline().rstrip().split sys.stdin.readline().rstrip() sys.stdin.readline().rstrip sys.stdin.readline() sys.stdin.readline sys.stdin sys stdin readline rstrip split sep for s in sys.stdin.readline().rstrip().split(sep) t(s) t s return [t(s) for s in sys.stdin.readline().rstrip().split(sep)] [t(s) for s in sys.stdin.readline().rstrip().split(sep)] t = str t str sep = " " sep " " def dprint(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)
    return dprint if DEBUG:
        print(*args, **kwargs)
     DEBUG print(*args, **kwargs) print *args args **kwargs kwargs return *args **kwargs def main():
    read()
    s = read()

    a_ord = ord("a")
    bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)}

    apps = SegmentTree(len(s), lambda x, y: x | y, 0)
    i = 0
    for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

    nr_q = read(int)
    for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges main read() read s = read() s read() read a_ord = ord("a") a_ord ord("a") ord "a" chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1) for c_ord in range(ord("a"), ord("z") + 1) c_ord range(ord("a"), ord("z") + 1) range ord("a") ord "a" ord("z") + 1 ord("z") ord "z" 1 for c_ord in range(ord("a"), ord("z") + 1) chr(c_ord) chr c_ord c_ord - a_ord c_ord a_ord bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)} bit_offsets {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)} apps = SegmentTree(len(s), lambda x, y: x | y, 0) apps SegmentTree(len(s), lambda x, y: x | y, 0) SegmentTree len(s) len s lambda x, y: x | y x | y x y x y 0 i = 0 i 0 for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

     c s apps.update(i, 1 << bit_offsets[c]) apps.update apps update i 1 << bit_offsets[c] 1 bit_offsets[c] bit_offsets c i += 1 i 1 nr_q = read(int) nr_q read(int) read int for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges i range(0, nr_q) range 0 nr_q q = read_list() q read_list() read_list if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges q[0] == "1" q[0] q 0 "1" _, i, c = q _ q i c apps.update(int(i) - 1, 1 << bit_offsets[c]) apps.update apps update int(i) - 1 int(i) int i 1 1 << bit_offsets[c] 1 bit_offsets[c] bit_offsets c _, l, r = q _ q l r print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1")) print bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1") (apps.query(int(l) - 1, int(r) - 1 + 1)).count (apps.query(int(l) - 1, int(r) - 1 + 1)) bin apps.query(int(l) - 1, int(r) - 1 + 1) apps.query apps query int(l) - 1 int(l) int l 1 int(r) - 1 + 1 int(r) - 1 int(r) int r 1 1 count "1" if __name__ == "__main__":
    main() __name__ == "__main__" __name__ "__main__" main() main def read(t = str):
    return t(sys.stdin.readline().rstrip()) def read(t = str):
    return t(sys.stdin.readline().rstrip()) read def read_list(t = str, sep = " "):
    return [t(s) for s in sys.stdin.readline().rstrip().split(sep)] def read_list(t = str, sep = " "):
    return [t(s) for s in sys.stdin.readline().rstrip().split(sep)] read_list DEBUG = False False DEBUG def main():
    read()
    s = read()

    a_ord = ord("a")
    bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)}

    apps = SegmentTree(len(s), lambda x, y: x | y, 0)
    i = 0
    for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

    nr_q = read(int)
    for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges def main():
    read()
    s = read()

    a_ord = ord("a")
    bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)}

    apps = SegmentTree(len(s), lambda x, y: x | y, 0)
    i = 0
    for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

    nr_q = read(int)
    for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges main class SegmentTree:

    # Use 1-based index internally
    def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
    def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
    def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc class SegmentTree:

    # Use 1-based index internally
    def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
    def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
    def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc SegmentTree def dprint(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)
    return def dprint(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)
    return dprint
#!/usr/bin/env python3

import sys

DEBUG = False


class SegmentTree:

    # Use 1-based index internally
    def __init__(self, n, merge_func, fillval=sys.maxsize):
        self.n = 1
        while self.n < n:
            self.n *= 2
        self.nodes = [fillval] * (self.n * 2 - 1 + 1)  # +1 for 1-based index
        self.merge_func = merge_func
        self.fillval = fillval
    
    def update(self, idx, val):
        idx += 1  # for 1-based index

        nodes = self.nodes
        mergef = self.merge_func

        idx += self.n - 1
        nodes[idx] = val
        while idx > 1: # > 1 for 1-based index
            idx >>= 1  # parent(idx) = idx >> 1 for 1-based index segment tree
            nodes[idx] = mergef(nodes[idx << 1], nodes[(idx << 1) + 1]) # child(idx) = idx << 1 and idx << 1 + 1
    
    def query(self, l, r):
        l += 1; r += 1  # for 1-based index

        l += self.n - 1
        r += self.n - 1
        acc = self.fillval
        while l < r:
            if l & 1:
                acc = self.merge_func(acc, self.nodes[l])
                l += 1
            if r & 1:
                acc = self.merge_func(acc, self.nodes[r - 1])
                r -= 1
            l >>= 1
            r >>= 1
        return acc

def read(t = str):
    return t(sys.stdin.readline().rstrip())

def read_list(t = str, sep = " "):
    return [t(s) for s in sys.stdin.readline().rstrip().split(sep)]

def dprint(*args, **kwargs):
    if DEBUG:
        print(*args, **kwargs)
    return


def main():
    read()
    s = read()

    a_ord = ord("a")
    bit_offsets = {chr(c_ord): c_ord - a_ord for c_ord in range(ord("a"), ord("z") + 1)}

    apps = SegmentTree(len(s), lambda x, y: x | y, 0)
    i = 0
    for c in s:
        apps.update(i, 1 << bit_offsets[c])
        i += 1

    nr_q = read(int)
    for i in range(0, nr_q):
        q = read_list()
        if q[0] == "1":
            _, i, c = q  # i_q in the question starts from 1, not 0
            apps.update(int(i) - 1, 1 << bit_offsets[c])
        else:
            _, l, r = q  # l_q and r_q in the question start from 1, not 0
            print(bin(apps.query(int(l) - 1, int(r) - 1 + 1)).count("1"))  # query in the question includes both edges


if __name__ == "__main__":
    main()