#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i=0;i<static_cast<int>(n);++i)
#define per(i, n) for(int i=static_cast<int>(n)-1;i>=0;--i)
#define eee(a) (cerr<<(#a)<<": "<<(a)<<'\n');
#define ppp(a) (cout<<(a)<<'\n'); 
#define cop(a) for(auto x:(a)){cerr<<(x)<<'\n';}
using ll = long long;
constexpr int dx[4]={1,0,-1,0};
constexpr int dy[4]={0,1,0,-1};
constexpr ll MOD = 1e9+7;
constexpr ll Mod = 998244353;
constexpr int INF = 1e9;
constexpr ll LINF = 1e18;
constexpr double phi = (1+sqrt(5))/2;
constexpr double pi = 3.14159265358979323846264338327950288;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll inverse(ll n,ll m=MOD){ll a=n,b=m,x=1,y=0;while(b){ll t=a/b;a-=t*b;swap(a,b);x-=t*y;swap(x,y);}return (a%m+m)%m;}
inline void Yes(){puts("Yes");}
inline void No(){puts("No");}
inline void Judge(bool b){b?Yes():No();}
inline void YES(){puts("YES");}
inline void NO(){puts("NO");}
inline void JUDGE(bool b){b?YES():NO();}
inline ll powmod(ll b, ll e, ll m=MOD){ll r=1;while(e>0){if(e&1)r=(r%m)*(b%m)%m;b=(b%m)*(b%m)%m;e>>=1;}return r;}
inline double distance(ll x1, ll y1, ll x2, ll y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
inline double d2r(double d){return d*pi/180;}
inline double r2d(double r){return r*180/pi;}
template<class T>inline bool chmax(T &a, const T &b){if(a<b){a=b;return 1;}return 0;}
template<class T>inline bool chmin(T &a, const T &b){if(b<a){a=b;return 1;}return 0;}
template<typename T1,typename T2>ostream& operator<<(ostream& s,const pair<T1, T2>& p){return s <<"("<<p.first<<", "<<p.second<<")";}
template<typename T> ostream& operator<<(ostream& s,const vector<T>& v){s<<'[';for(size_t i=0;i<v.size();++i){s<<v[i];if(i<v.size()-1)s<<", ";}s<<']';return s;}

template <class T>
class SegmentTree{
    private:
        int n;
        vector<T> data;
        T def;
        function<T(T,T)> operation;
        function<T(T,T)> update;

        T _query(int a, int b, int k, int l, int r){
            if(r <= a or b <= l) return def;

            if(a <= l and r <= b) return data[k];
            else{
                T c1 = _query(a, b, 2*k+1, l, (l+r)/2);
                T c2 = _query(a, b, 2*k+2, (l+r)/2, r);
                return operation(c1, c2);
            }
        }

    public:
        SegmentTree(size_t n_, T _def, function<T(T,T)> _operation, function<T(T,T)> _update)
            : def(_def), operation(_operation), update(_update){
                n = 1; while(n < n_) n *= 2;
                data = vector<T>(2*n-1, def);
            }

        void change(int i, bitset<26> val){
            i += n-1;
            data[i] = update(data[i], val);
            while(i > 0){
                i = (i-1)/2;
                data[i] = operation(data[2*i+1], data[2*i+2]);
            }
        }

        T query(int a, int b){
            return _query(a, b, 0, 0, n);
        }

        T operator[](int i){
            return data[i+n-1];
        }

};

int main(){
    cin.tie(0); ios::sync_with_stdio(0); cout<<fixed<<setprecision(15);
    
    int n; cin >> n;
    string s; cin >> s;

    SegmentTree<bitset<26>> st(n, bitset<26>(), 
            [](bitset<26> a, bitset<26> b){return a|b;},
            [](bitset<26> a, bitset<26> b){return b;});

    rep(i, n){
        bitset<26> bs;
        bs.set(s[i]-'a');
        st.change(i, bs);
    }

    int q; cin >> q;
    rep(i, q){
        int X, L;
        string R;
        cin >> X >> L >> R;
        if(X == 1){
            bitset<26> bs;
            bs.set(R[0]-'a');
            st.change(L-1, bs);
        }
        if(X == 2){
            int RR = stoi(R);
            cout << st.query(L-1, RR).count() << endl;
        }
    }

    return 0;
}


Measured memory_bytes: 9116