#include <bits/stdc++.h>
using namespace std;
template <typename type>
type __lcm(type n1, type n2) {
  return n1 * (n2 / __gcd(n1, n2));
}
long long nCr(int n, int r) {
  int f1 = r, f2 = n - r;
  if (f2 > f1) swap(f2, f1);
  long long result = 1;
  for (int i = 1; i <= f2; i++) {
    result *= (i + f1);
    result /= i;
  }
  return result;
}
long long nPr(int n, int r, long long mod = 0) {
  long long result = 1;
  for (int i = n - r + 1; i <= n; i++) {
    result *= i;
    if (mod) result %= mod;
  }
  return result;
}
long long factorial(int n, long long modulo = 0) {
  if (n == 0) return 1;
  if (modulo)
    return (n * factorial(n - 1)) % modulo;
  else
    return n * factorial(n - 1);
}
int *primes = NULL;
bool *isPrime = NULL;
int pidx = 0;
void normal_sieve(int n) {
  n += 5;
  isPrime = new bool[n];
  memset(isPrime, 1, n);
  int sq = sqrt(n);
  isPrime[0] = isPrime[1] = false;
  for (int i = 4; i < n; i += 2) isPrime[i] = false;
  for (int i = 3; i <= sq; i += 2)
    if (isPrime[i])
      for (int j = i * i; j < n; j += (i << 1)) isPrime[j] = false;
  int primeCount = 1;
  for (int i = 3; i < n; i += 2) primeCount += (isPrime[i]);
  primes = new int[primeCount];
  primes[pidx++] = 2;
  for (int i = 3; i < n; i += 2)
    if (isPrime[i]) primes[pidx++] = i;
}
int *isbPrime = NULL;
void bitwise_sieve(int n) {
  n += 5;
  int array_size = (n >> 5);
  isbPrime = new int[array_size];
  memset(isbPrime, 0, n >> 3);
  int sq = sqrt(n);
  (isbPrime[0 >> 5] = isbPrime[0 >> 5] or (1 << (0 % 32)));
  (isbPrime[1 >> 5] = isbPrime[1 >> 5] or (1 << (1 % 32)));
  for (int i = 4; i < 64; i += 2)
    (isbPrime[i >> 5] = isbPrime[i >> 5] or (1 << (i % 32)));
  for (int i = 2; i < array_size; i++) isbPrime[i] = isbPrime[1];
  for (int i = 3; i <= sq; i += 2)
    if (!(isbPrime[i >> 5] & (1 << (i % 32))))
      for (int j = i * i; j < n; j += (i << 1))
        (isbPrime[j >> 5] = isbPrime[j >> 5] or (1 << (j % 32)));
}
void f();
int main() {
  ios_base ::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t = 1;
  for (int(i) = (1); (i) <= (t); (i)++) {
    f();
  }
  return 0;
}
string s;
int tree[2000010][26];
void init(int b, int e, int node) {
  int mid = (b + e) >> 1, lft = node << 1, rgt = lft + 1;
  if (b == e) {
    tree[node][s[b] - 'a']++;
    return;
  }
  init(b, mid, lft);
  init(mid + 1, e, rgt);
  for (int i = 0; i < 26; i++) {
    tree[node][i] = tree[lft][i] + tree[rgt][i];
  }
}
void update(int node, int b, int e, int poss, char c) {
  int lft = node << 1, rgt = lft + 1, mid = (b + e) >> 1;
  if (b > poss || e < poss) return;
  if (b == poss && e == poss) {
    tree[node][s[b] - 'a']--;
    s[b] = c;
    tree[node][s[b] - 'a']++;
    return;
  }
  update(lft, b, mid, poss, c);
  update(rgt, mid + 1, e, poss, c);
  for (int i = 0; i < 26; i++) {
    tree[node][i] = tree[lft][i] + tree[rgt][i];
  }
}
vector<int> dummy(26);
vector<int> query(int node, int b, int e, int st, int en) {
  int lft = node << 1, rgt = lft + 1, mid = (b + e) >> 1;
  if (b > en || e < st) return dummy;
  if (b >= st && e <= en) {
    int cnt = 0;
    vector<int> ret(26);
    for (int i = 0; i < 26; i++) {
      ret[i] = tree[node][i];
    }
    return ret;
  }
  vector<int> ret1 = query(lft, b, mid, st, en);
  vector<int> ret2 = query(rgt, mid + 1, e, st, en);
  for (int i = 0; i < 26; i++) {
    ret1[i] += ret2[i];
  }
  return ret1;
}
void f() {
  for (int i = 0; i < 26; i++) {
    dummy[i] = 0;
  }
  int n;
  cin >> n;
  cin >> s;
  s = '|' + s;
  init(1, n, 1);
  int q;
  cin >> q;
  while (q--) {
    int ch;
    cin >> ch;
    if (ch == 1) {
      int poss;
      char up;
      cin >> poss >> up;
      update(1, 1, n, poss, up);
    } else {
      int l, r;
      cin >> l >> r;
      vector<int> ans;
      ans = query(1, 1, n, l, r);
      int cnt = 0;
      for (int i = 0; i < 26; i++) {
        if (ans[i] > 0) cnt++;
      }
      cout << cnt << '\n';
    }
  }
}
