#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<(n); ++i)
#define rep2(i, s, n) for(int i=s; i<(n); ++i)
#define ALL(v) (v).begin(), (v).end()

using namespace std;

typedef long long ll;

static const int INTINF = (2147483647 >> 1); // 10^9 + 5000
static const ll LLINF = (9223372036854775807 >> 1);
static const int MAX = 1e5+1;
static const ll MOD = 1e9+7;

namespace Kunitaka{
    template<
        typename TYPE,
        std::size_t SIZE
    >
    std::size_t array_length(const TYPE (&array)[SIZE])
    {
        return SIZE;
    }
}
using namespace Kunitaka;
namespace Printer{
    void br(){
        cout << endl;
    }

    void loop_cnt(int i){
        cout << "i = " << i << endl;
    }

    void loop_cnt(int i, int j){
        cout << "i = " << i << ", " << "j = " << j << endl;
    }

    template<class T>
    void print(T x){
        cout << x << endl;
    }

    template<class T, class S>
    void print(T x, S y){
        cout << x << "," << y << endl;
    }

    template<class T, class S, class U>
    void print(T x, S y, U z){
        cout << x << "," << y << "," << z << endl;
    }

    template<class T, class S>
    void print(pair<T, S> p){
        cout << p.first << ", " << p.second << endl;
    }

    template<
        typename TYPE,
        std::size_t SIZE
    >
    void print(const TYPE (&array)[SIZE]){
        int lim = array_length(array);
        for(int i=0; i<lim; i++){
            if(i) cout << " ";
            cout << array[i];
        }
        cout << endl;
    }

    template<class S>
    void print(vector<S> v){
        for(int i=0; i<v.size(); i++){
            if(i) cout << " ";
            cout<< v[i];
        }
        cout << endl;
    }

    template<class S>
    void print(vector<vector<S> > vv){
        for(int i=0; i<vv.size(); i++){
            for(int j=0; j<vv[i].size(); j++){
                if(j) cout << " ";
                cout << vv[i][j];
            }
            cout << endl;
        }
    }

    void yesno(bool x){
        if(x) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
};
using namespace Printer;

class LazySegmentTree {
    private:
        ll INTINF = 2147483647 >> 1; // 2147483647 >> 1
        ll n;
        vector<vector<bool> > node, lazy;
        vector<bool> lazyFlag;
        bool isMax = false;

    public:
        void init(vector<vector<bool> > v) {
            ll sz = v.size();
            n = 1; while(n < sz) n *= 2;
            vector<bool> tmp(30);
            fill(ALL(tmp), false);
            node.resize(2*n-1, tmp);
            lazy.resize(2*n-1, tmp);
            lazyFlag.resize(2*n-1, false);

            for(ll i=0; i<sz; i++) node[i+n-1] = v[i];
            for(ll i=n-2; i>=0; i--) node[i] = compare(node[i*2+1], node[i*2+2]);
        }

        // k 番目のノードについて遅延評価を行う
        void lazyEvaluate(ll k, ll l, ll r) {
            if(lazyFlag[k]) {
                node[k] = lazy[k];
                if(r - l > 1) {
                    lazy[k*2+1] = lazy[k*2+2] = lazy[k];
                    lazyFlag[k*2+1] = lazyFlag[k*2+2] = true;
                }
                lazyFlag[k] = false;
            }
        }

        // 遅延評価を考慮した区間更新：[a, b)をxに更新
        void update(ll a, ll b, vector<bool> x, ll k=0, ll l=0, ll r=-1) {
            if(r < 0) r = n;
            lazyEvaluate(k, l, r);
            if(b <= l || r <= a) return;
            if(a <= l && r <= b) {
                lazy[k] = x;
                lazyFlag[k] = true;
                lazyEvaluate(k, l, r);
            }
            else {
                update(a, b, x, 2*k+1, l, (l+r)/2);
                update(a, b, x, 2*k+2, (l+r)/2, r);
                node[k] = compare(node[2*k+1], node[2*k+2]);
            }
        }

        // [a, b)の最小値を検索
        vector<bool> find(ll a, ll b, ll k=0, ll l=0, ll r=-1) {
            if(r < 0) r = n;
            lazyEvaluate(k, l, r);
            if(b <= l || r <= a) {
                vector<bool> tmp(30);
                fill(ALL(tmp), false);
                return tmp;
            }
            if(a <= l && r <= b) return node[k];
            vector<bool> vl = find(a, b, 2*k+1, l, (l+r)/2);
            vector<bool> vr = find(a, b, 2*k+2, (l+r)/2, r);
            return compare(vl, vr);
        }

        vector<bool> getNode(ll index){
            return node[index + n / 2];
        }

        vector<bool> compare(vector<bool> a, vector<bool> b){
            rep(i, a.size()){
                a[i] = max(a[i], b[i]);
            }
            return a;
        }
};

int main(int argc, const char * argv[]) {
    //提出時、消す----//
    //--------------//


    // input
    cout << fixed << setprecision(10);
    ll N; cin >> N;
    string S; cin >> S;
    ll Q; cin >> Q;
    LazySegmentTree seg;
    vector<vector<bool> > v(S.size());
    rep(i, S.size()){
        vector<bool> tmp(30);
        fill(ALL(tmp), 0);
        tmp[S[i] - 'a'] = true;
        v[i] = tmp;
    }
    // print(v);
    seg.init(v);


    // variable
    ll ans = 0;
    // solve
    // 1 -> change
    // 2 -> out
    rep(i, Q){
        ll type; cin >> type;
        if(type == 1){
            // change
            ll l; cin >> l;
            l--;
            char a; cin >> a;
            vector<bool> tmp(30);
            fill(ALL(tmp), false);
            tmp[a - 'a'] = true;
            seg.update(l, l+1, tmp);
        }
        else{
            // out
            ll l, r; cin >> l >> r;
            l--; r--;
            vector<bool> res = seg.find(l, r+1);
            ll out = 0;
            rep(i, 30){
                if(res[i])out++; 
            }
            print(out);
        }
    }
    
    return 0;
}


Measured memory_bytes: 218628