#include <bits/stdc++.h>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *min_element(all(a))
#define MAX(a) *max_element(all(a))
#define SUM(a) accumulate(all(a), 0LL)
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define RREP(i, n) for(int (i)=(n)-1; (i)>=0; (i)--)
#define FOR(i, m, n) for(int (i)=(m); (i)<(n); i++)
#define FORR(i, m, n) for(int (i)=(n)-1; (i)>=(m); i--)
#define debug(x) cerr << #x << " = " << x << endl
//#define int long long

typedef long long ll;
//ll const MOD = 998244353;
ll const MOD = 1e9+7;
int const inf = 1e9;
ll const INF = 1e18;

inline void ios_(){cin.tie(0); ios::sync_with_stdio(false);}
template<typename T> int size(const T& a){return (int)a.size();}
template<typename T> T Div(T a, T b){return (a + b - 1) / b;}
template<typename T> bool chmin(T& a, const T& b){if(a > b){a = b; return true;} return false;}
template<typename T> bool chmax(T& a, const T& b){if(a < b){a = b; return true;} return false;}

template<typename T> class SegmentTree{
public:
    int N;                  //要素数
    int rank;               //階数
    T idt;                  //単位元
    vector<T> node;         //ノード (1-indexed, node[0]=idt)
    function<T(T,T)> fn;    //二項演算


    //要素を引数のベクトルから受け取る
    SegmentTree(const vector<T>& v, T id, function<T(T,T)> f) : idt(id), fn(f){
        N = v.size();
        rank = calcRank(N);
        node.resize(1 << (rank + 1));
        
        int r = 1 << rank;
        for(int i=0; i<2*r; i++){
            if(i >= r && i < r + N){    //最下層のノードに要素を格納
                node[i] = v[i - r];
            }else{
                node[i] = idt;
            }
        }

        build();
    }

    int calcRank(int n){
        int res = 0;
        n--;
        while(n > 0){
            res++;
            n /= 2;
        }
        return res;
    }

    void build(){
        int r = 1 << rank;
        for(int i=r-1; i>0; i--){
            node[i] = fn(node[2*i], node[2*i + 1]);
        }
    }

    void update(int i, T value){    //値の更新
        int n = i + (1 << rank);    //要素番号->ノード番号
        node[n] = value;

        while(n > 1){
            n /= 2;
            node[n] = fn(node[2*n], node[2*n + 1]); //上に向かって値を更新する
        }
    }

    T query(int a, int b){  //半開区間 [a,b) に対するクエリ
        return range(a, b, 1, 0, 1 << rank);
    }

    T range(int a, int b, int k, int l, int r){ //計算用の内部関数
        if(r <= a || b <= l){   //[a,b) と [l,r) が交差しない場合
            return idt;
        }
        if(a <= l && r <= b){   //[l,r) が [a,b) に含まれる場合
            return node[k];
        }

        T vl = range(a, b, 2*k, l, (l+r)/2);    //左右に分けて再帰
        T vr = range(a, b, 2*k+1, (l+r)/2, r);

        return fn(vl, vr);
    }
};


signed main(){
    int n;
    string s;
    cin >> n >> s;

    vector<int> v(n);
    REP(i, n){
        v[i] = 1 << (s[i] - 'a');
    }

    SegmentTree<int> tree(v, 0, [](int a, int b){return a | b;});

    int q;
    cin >> q;
    REP(i, q){
        int t;
        cin >> t;
        if(t == 2){
            int l, r;
            cin >> l >> r;
            cout << __builtin_popcount(tree.query(l-1, r)) << endl;
        }else{
            int d;
            char c;
            cin >> d >> c;
            tree.update(d-1, (1 << (c - 'a')));
        }
    }

    return 0;
}


Measured memory_bytes: 6916