### BUGGY CODE ###

N = [int(i) for i in input().split()][0]
string = list(input())
Q = [int(i) for i in input().split()][0]
queries = [[i for i in input().split()] for _ in range(Q)]

tmp = N 
c = 0
while tmp > 0:
  c += 1
  tmp //= 2
N2 = 2**c

seg_trees = [[0 for _ in range(N2*2 -1)] for _ in range(26)]
for n in range(N):
  ind = ord(string[n]) - ord("a")
  for i in range(26):
    seg_trees[i][N2-1+n] = 1 if ind == i else 0

def set_seg_tree(i, seg_tree):
  if i >= N2 -1:
    return seg_tree[i]
  left = 2*i + 1
  right = 2*i + 2
  l_seg = set_seg_tree(left, seg_tree)
  r_seg = set_seg_tree(right, seg_tree)
  seg_tree[i] = l_seg + r_seg
  return seg_tree[i]
for i in range(26):
  set_seg_tree(0, seg_trees[i])

def modify(i, x, seg_tree):
  i += N2 -1
  seg_tree[i] = x
  while i > 0:
    i = (i - 1)//2
    seg_tree[i] = seg_tree[i * 2 + 1] + seg_tree[i * 2 + 2]
    
def modify_diff(i, diff, seg_tree):
  i += N2 -1
  seg_tree[i] += diff
  while i > 0:
    i = (i - 1)//2
    seg_tree[i] = seg_tree[i * 2 + 1] + seg_tree[i * 2 + 2]

def get_sum(a, b, k, l, r, seg_tree):
  if (b <= l) or (r <= a):
    return 0
  if (a <= l) and (r <= b):
    return seg_tree[k]
  vl = get_sum(a, b, k * 2 + 1, l, (l + r)//2, seg_tree)
  vr = get_sum(a, b, k * 2 + 2, (l + r)//2, r, seg_tree)
  return vl + vr

#print(seg_trees[1])
#modify(0, 1, seg_trees[1])
#print(seg_trees[1])
#print(get_sum(0, 3, 0, 0, N2, seg_trees[1]))
#print(get_sum(1, 6, 0, 0, N2, seg_trees[1]))
for query in queries:
  type_, i, q = query
  if type_ == "1":
    i = int(i) - 1
    pos = ord(q) - ord("a")
    old = ord(string[i]) - ord("a")
    string[i] = q
    modify_diff(i, 1, seg_trees[pos])
    modify_diff(i, -1, seg_trees[old])
  else:
    l = int(i) - 1
    r = int(q)
    counts = 0
    for i in range(26):
      ret = get_sum(l, r, 0, 0, N2, seg_trees[i])
      counts += (1 if ret > 0 else 0)
    print(counts)




### FIXED CODE ###



N = [int(i) for i in input().split()][0]
string = list(input())
Q = [int(i) for i in input().split()][0]
queries = [[i for i in input().split()] for _ in range(Q)]

tmp = N 
c = 0
while tmp > 0:
  c += 1
  tmp //= 2
N2 = 2**c
offset = N2 - 1

seg_tree = [0 for _ in range(N2*2 -1)]
for n in range(N):
  ind = ord(string[n]) - ord("a")
  seg_tree[offset + n] = 1 << ind

def set_seg_tree(i, seg_trees):
  if i >= N2 -1:
    return seg_trees[i]
  left = 2*i + 1
  right = 2*i + 2
  l_seg = set_seg_tree(left, seg_trees)
  r_seg = set_seg_tree(right, seg_trees)
  seg_trees[i] = l_seg | r_seg
  return seg_trees[i]
set_seg_tree(0, seg_tree)
    
def update(i, c, seg_trees):
  i += offset
  seg_trees[i] = 1 << c
  while i > 0:
    i = (i - 1)//2
    seg_trees[i] = seg_trees[i * 2 + 1] | seg_trees[i * 2 + 2]

def get_sum(a, b, k, l, r, seg_trees):
  if (b <= l) or (r <= a):
    return 0
  if (a <= l) and (r <= b):
    return seg_trees[k]
  vl = get_sum(a, b, k * 2 + 1, l, (l + r)//2, seg_trees)
  vr = get_sum(a, b, k * 2 + 2, (l + r)//2, r, seg_trees)
  return vl | vr

for query in queries:
  type_, i, q = query
  if type_ == "1":
    i = int(i) - 1
    pos = ord(q) - ord("a")
    update(i, pos, seg_tree)
  else:
    l = int(i) - 1
    r = int(q)
    ret = get_sum(l, r, 0, 0, N2, seg_tree)
    print(bin(ret).count("1"))