// Original C++ solution (slower):
#include <iostream>

#include <string>

#include <vector>

#include <deque>

#include <queue>

#include <algorithm>

#include <set>

#include <map>

#include <bitset>

#include <cmath>

#include <functional>

#include <iomanip>

#define vll vector<ll>

#define vvv vector<vvl>

#define vvi vector<vector<int> >

#define vvl vector<vector<ll> >

#define vv(a, b, c, d) vector<vector<d> >(a, vector<d>(b, c))

#define vvvl(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));

#define rep(c, a, b) for(ll c=a;c<b;c++)

#define re(c, b) for(ll c=0;c<b;c++)

#define all(obj) (obj).begin(), (obj).end()

typedef long long int ll;

typedef long double ld;

typedef __int128_t lll;

using namespace std;



//-------------------------------------------------------------------

struct segtree{

  ll M=1, INIT;

  vector<ll> dat;

  segtree(ll N, ll num){

    INIT = num;

    while(M<N) M*=2;

    for(int i=0;i<M*2-1;i++)  dat.push_back(num);

  }

  void update(ll x, ll k, ll l=0, int r=-1){

    if(r==-1) r = M;

    k+=M-1;

    dat[k] = x;

    while(k>0) k = (k-1)/2, dat[k] = dat[k*2+1] + dat[k*2+2];

  }

  ll query(ll a, ll b=-1, ll k=0, ll l=0, ll r=-1){

    if(r==-1) r = M;

    if(b==-1) b = M;

    if(r<=a || b<=l) return INIT;

    if(a<=l && r<=b) return dat[k];

    ll A = query(a, b, k*2+1, l, (l+r)/2);

    ll B = query(a, b, k*2+2, (l+r)/2, r);

    return A + B;

  }

};

//-------------------------------------------------------------------

int main(int argc, char const *argv[]) {

  ll n;std::cin >> n;

  string s;std::cin >> s;

  ll q;std::cin >> q;

  vector<segtree> seg(26, segtree(n+100, 0));



  re(i, n){

    ll now = s[i]-'a';

    seg[now].update(1, i);

  }



  re(i, q){

    ll a, b;scanf("%lld %lld",&a, &b);

    if(a==1){

      char c;std::cin >> c;

      ll pre = s[b-1]-'a';

      ll to = c-'a';

      s[b-1] = c;

      seg[pre].update(0, b-1);

      seg[to].update(1, b-1);

    }else{

      ll c, ans = 0;std::cin >> c;

      re(j, 26){

        ll q = seg[j].query(b-1, c);

        if(q>0) ans++;

      }

      std::cout << ans << '\n';

    }

  }

  return 0;

}


// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

#include <string>

#include <functional>

typedef long long int ll;

using namespace std;





template<typename T>

struct segtree{

  typedef function<T(T*, T*)> G; //merge

  typedef function<T(T*, T*)> H; //update

  ll M=1;

  G g;

  H h;

  T UNIT;

  vector<T> dat;



  segtree(ll N, T unit, G merge_func, H update_func):UNIT(unit){

    g = merge_func;

    h = update_func;

    while(M<N) M*=2;

    dat.resize(M*2-1, unit);

  }



  void update(T x, ll k, ll l=0, int r=-1){

    if(r==-1) r = M;

    k+=M-1;

    dat[k] = h(&dat[k], &x);

    while(k>0) {

      k = (k-1)/2;

      dat[k] = g(&dat[k*2+1], &dat[k*2+2]);

    }

  }



  T query(ll a, ll b=-1, ll k=0, ll l=0, ll r=-1){

    if(r==-1) r = M;

    if(b==-1) b = M;

    if(r<=a || b<=l) return UNIT;

    if(a<=l && r<=b) return dat[k];

    T A = query(a, b, k*2+1, l, (l+r)/2);

    T B = query(a, b, k*2+2, (l+r)/2, r);

    return g(&A, &B);

  }

};

ll mg(ll* a, ll* b){return *a|*b;}

ll upd(ll* old_elem, ll* new_elem){return *old_elem^*new_elem;}



int main(int argc, char const *argv[]) {

  ll n;std::cin >> n;

  string s;std::cin >> s;

  ll q;std::cin >> q;

  segtree<ll> seg(n+1, 0, mg, upd);

  for(int i=0;i<n;i++) seg.update(1<<(s[i]-'a'), i);

  for(int i=0;i<q;i++){

    ll a, b;std::cin >> a >> b;

    b--;

    if(a==1){

      char c;std::cin >> c;

      int pre = s[b] - 'a';

      int nw = c - 'a';

      seg.update((1<<pre), b);

      seg.update((1<<nw), b);

      s[b] = c;

    }else{

      ll c;std::cin >> c;

      ll q = seg.query(b, c);

      ll cnt = 0;

      for(int j=0;j<26;j++) if((q>>j)&1) cnt++;

      std::cout << cnt << '\n';

    }

  }

  return 0;

}


// Fastest known solution for this problem: