#include <bits/stdc++.h>
#define lli long long int
#define pb push_back
#define mod 1000000007
#pragma GCC optimize ("-O3")
#define mod2 998244353
#define MAXN 1000000000
#define v32 vector<int>
#define v64 vector<lli>
#define v1024 vector <vector <int>>
#define v4096 vector <vector <lli>>
#define vt vector
#define f(x, y, z) for (lli x = y; x < z; x++)
#define fd(x, y, z) for (lli x = y; x > z; x--)
#define lb lower_bound
#define ld long double
#define m64 map<lli,lli>
#define m32 map<int,int>
#define m64it map<lli,lli>::iterator
#define m32it map<int,int>::iterator
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define ist insert
#define endl "\n"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> 
#define p_q priority_queue 
#define min_p_q priority_queue <int,vt <int>,greater <int>>
using namespace std;
using namespace __gnu_pbds; 

template <typename T> 
void DEBUG_ARR(vt<T> a,char c)
{
	f(i,0,a.size())cout<<a[i]<<c;
	cout<<"\n";
}

lli tmod(lli x,lli m=mod){return (x%m+m)%m;}//USE AT YOUR OWN RISK
lli power(lli x, lli y) 
{
    lli res = 1;  
   
    while (y > 0) 
    { 
        if (y & 1) 
            res = (res*x)%mod; 
        y = y>>1; 
        x = (x*x)%mod;  
    }
    if(res<0)
       res+=mod; 
    return res; 
}
// lli fact[2000009];
// lli ncr(lli n,lli r){
//     lli ans=fact[n];
//     if(r>n)return 0;
//     ans=(ans*power(fact[n-r],mod-2))%mod;
//     ans=(ans*power(fact[r],mod-2))%mod;
//     return ans;
// }
class RMQv //returns max-min value in a given range
{
    public:
	struct node
    {
	int mn,mx,l,r; 
    };
	v32 h;
	vt <node> st;
	RMQv(v32 a)
	{
       h=a;
       st.resize(4*h.size());
       build(0,h.size()-1);
	}
	void build(int l,int r,int k=0)
	{
		st[k].l=l,st[k].r=r;
	    if(l==r)
		   {st[k].mx=st[k].mn=h[l];
             return;
		   }
	    build(l,(l+r)>>1,2*k+1);
	    build(((l+r)>>1)+1,r,2*k+2);
      st[k].mx=(st[2*k+1].mx|st[2*k+2].mx); 
	}
	int maxquery(int l,int r,int k=0)
    {
       if(l>r)return 0;
       int ll=st[k].l,rr=st[k].r,mid=(ll+rr)>>1;
       if(r<ll || l>rr)return 0;
       if(ll>=l && rr<=r)
          return st[k].mx;
   	   int ans=0;   
   	   ans=maxquery(l,r,2*k+1);
   	   ans=(ans|maxquery(l,r,2*k+2));
   	   return ans;     
    }
    void update(int id,int val,int k=0)
    {
        int l=st[k].l,r=st[k].r,mid=(l+r)>>1;
        if(id<l || id>r)return;
        if(l==r)
        {
            st[k].mx=val;
            return;
        }
        update(id,val,2*k+1);
        update(id,val,2*k+2);
        st[k].mx=(st[2*k+1].mx|st[2*k+2].mx); 
    }
};
int main() 
{ 
    // fact[0]=1;
    // f(i,1,2000001)fact[i]=(i*fact[i-1])%mod;
    fastio;
    int t;
    // cin>>t;	
    t=1;
	while(t--){
        int n;
        cin>>n;
        string s;cin>>s;
        int q;cin>>q;
        v32 forST(n);f(i,0,n)forST[i]=(1<<(s[i]-'a'));
        RMQv ST(forST);
        while(q--){
            int t;cin>>t;
            int l,r;char c;
            cin>>l;
            if(t==1)cin>>c;
            else cin>>r;
            if(t==1){
                l--;
                ST.update(l,(1<<(c-'a')));
            }
            else{
                l--,r--;
                cout<<__builtin_popcount(ST.maxquery(l,r))<<"\n";
            }
        }
	}

    return 0; 	
}

Measured memory_bytes: 38044