#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x) {
  x = 0;
  int f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') x = x * 10 + (ch ^ 48), ch = getchar();
  x *= f;
  return;
}
template <typename T>
void write(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10) write(x / 10);
  putchar(x % 10 + '0');
  return;
}
const int MAXN = 500010;
int n, q;
char ch[MAXN];
struct node {
  int l, r;
  bitset<25> s;
} f[MAXN * 4];
inline void pushup(int p) { f[p].s = f[p << 1].s | f[p << 1 | 1].s; }
void build(int p, int l, int r) {
  f[p].l = l, f[p].r = r;
  if (l == r) {
    f[p].s.reset();
    f[p].s[ch[l] - 'a' + 1] = 1;
    return;
  }
  int mid = (l + r) >> 1;
  build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
  pushup(p);
}
void modify(int p, int x, int c) {
  if (f[p].l == f[p].r) {
    f[p].s.reset();
    f[p].s[c] = 1;
    return;
  }
  int mid = (f[p].l + f[p].r) >> 1;
  if (x <= mid)
    modify(p << 1, x, c);
  else
    modify(p << 1 | 1, x, c);
  pushup(p);
}
bitset<25> query(int p, int l, int r) {
  if (f[p].l >= l && f[p].r <= r) return f[p].s;
  bitset<25> ret;
  ret.reset();
  int mid = (f[p].l + f[p].r) >> 1;
  if (l <= mid) ret = ret | query(p << 1, l, r);
  if (r > mid) ret = ret | query(p << 1 | 1, l, r);
  return ret;
}
int main() {
  read(n);
  scanf("%s", ch + 1);
  build(1, 1, n);
  read(q);
  for (int i = 1; i <= q; i++) {
    int op;
    read(op);
    if (op == 1) {
      int x;
      char y;
      read(x);
      scanf("%c", &y);
      modify(1, x, y);
    } else {
      int l, r;
      read(l), read(r);
      write(query(1, l, r).count()), putchar('\n');
    }
  }
  return 0;
}
