import bisect  # 配列二分法
from collections import defaultdict

N = int(input())
S = [*input()]
Q = int(input())
d = defaultdict(list)

# 各アルファベットの出現場所を記録
for i, c in enumerate(S):
    d[c] += [i]

# この時点でどのアルファベットについてもソート済み
# print(d)

for _ in range(Q):
    q, y, z = input().split()

    if q == '1':
        i = int(y) - 1  # 文字の変更位置

        if S[i] == z: continue  # 同じ文字の場合は処理終了

        # 削除 O(N)
        b = bisect.bisect(d[S[i]], i)  # 2分法で i の出現位置を(log N)で探す
        d[S[i]].pop(b - 1)  # 削除

        # 追加 O(N) かかる？
        S[i] = z
        bisect.insort(d[z], i) 

    else:
        left = int(y) - 1
        right = int(z) - 1

        count = 0
        for v in d.values():
            count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0

        print(count) import bisect bisect from collections import defaultdict N = int(input()) N int(input()) int input() input S = [*input()] S [*input()] *input() input() input Q = int(input()) Q int(input()) int input() input d = defaultdict(list) d defaultdict(list) defaultdict list for i, c in enumerate(S):
    d[c] += [i]

# この時点でどのアルファベットについてもソート済み
# print(d) i c enumerate(S) enumerate S d[c] += [i] d[c] d c [i] i for _ in range(Q):
    q, y, z = input().split()

    if q == '1':
        i = int(y) - 1  # 文字の変更位置

        if S[i] == z: continue  # 同じ文字の場合は処理終了

        # 削除 O(N)
        b = bisect.bisect(d[S[i]], i)  # 2分法で i の出現位置を(log N)で探す
        d[S[i]].pop(b - 1)  # 削除

        # 追加 O(N) かかる？
        S[i] = z
        bisect.insort(d[z], i) 

    else:
        left = int(y) - 1
        right = int(z) - 1

        count = 0
        for v in d.values():
            count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0

        print(count) _ range(Q) range Q q, y, z = input().split() q input().split() ().split () input split y z if q == '1':
        i = int(y) - 1  # 文字の変更位置

        if S[i] == z: continue  # 同じ文字の場合は処理終了

        # 削除 O(N)
        b = bisect.bisect(d[S[i]], i)  # 2分法で i の出現位置を(log N)で探す
        d[S[i]].pop(b - 1)  # 削除

        # 追加 O(N) かかる？
        S[i] = z
        bisect.insort(d[z], i) 

    else:
        left = int(y) - 1
        right = int(z) - 1

        count = 0
        for v in d.values():
            count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0

        print(count) q == '1' q '1' i = int(y) - 1 i int(y) - 1 int(y) int y 1 if S[i] == z: continue  # 同じ文字の場合は処理終了

        # 削除 O(N)
         S[i] == z S[i] S i z b = bisect.bisect(d[S[i]], i) b bisect.bisect(d[S[i]], i) bisect.bisect bisect bisect d[S[i]] d S[i] S i i d[S[i]].pop(b - 1) [S[i]].pop [S[i]] d S[i] S i pop b - 1 b 1 S[i] = z S[i] S i z bisect.insort(d[z], i) bisect.insort bisect insort d[z] d z i left = int(y) - 1 left int(y) - 1 int(y) int y 1 right = int(z) - 1 right int(z) - 1 int(z) int z 1 count = 0 count 0 for v in d.values():
            count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0

         v d.values() d.values d values count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0 count 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0 bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 bisect.bisect(v, right) - bisect.bisect_left(v, left) bisect.bisect(v, right) bisect.bisect bisect bisect v right bisect.bisect_left(v, left) bisect.bisect_left bisect bisect_left v left 0 1 0 print(count) print count b = bisect.bisect(d[S[i]], i) bisect.bisect(d[S[i]], i) b N = int(input()) int(input()) N count = 0 0 count left = int(y) - 1 int(y) - 1 left i = int(y) - 1 int(y) - 1 i z = input().split() input().split() z S = [*input()] [*input()] S right = int(z) - 1 int(z) - 1 right q, y, z = input().split() input().split() q y, z = input().split() input().split() y d = defaultdict(list) defaultdict(list) d Q = int(input()) int(input()) Q count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0 count
import bisect  # 配列二分法
from collections import defaultdict

N = int(input())
S = [*input()]
Q = int(input())
d = defaultdict(list)

# 各アルファベットの出現場所を記録
for i, c in enumerate(S):
    d[c] += [i]

# この時点でどのアルファベットについてもソート済み
# print(d)

for _ in range(Q):
    q, y, z = input().split()

    if q == '1':
        i = int(y) - 1  # 文字の変更位置

        if S[i] == z: continue  # 同じ文字の場合は処理終了

        # 削除 O(N)
        b = bisect.bisect(d[S[i]], i)  # 2分法で i の出現位置を(log N)で探す
        d[S[i]].pop(b - 1)  # 削除

        # 追加 O(N) かかる？
        S[i] = z
        bisect.insort(d[z], i) 

    else:
        left = int(y) - 1
        right = int(z) - 1

        count = 0
        for v in d.values():
            count += 1 if bisect.bisect(v, right) - bisect.bisect_left(v, left) > 0 else 0

        print(count)