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

template <typename T>
class SegmentTree{
public:
    SegmentTree(const vector<T>& v){
        m_depth = get_depth(v.size());
        m_N = (1 << m_depth) - 1;
        m_array.resize(m_N);

        auto s = get_shift(m_depth - 1);
        for(int i = 0; i < v.size(); i++){
            m_array.at(s + i) = v.at(i);
        }
        for(int i=v.size(); s + i< m_N; i++){
            m_array.at(s + i) = get_dummy_value();
        }
        for(int d=m_depth-2; d>=0; d--){
            auto s1 = get_shift(d);
            for(int i=0; i < (1<<d); i++){
                auto child = get_child_index(s1 + i);
                m_array.at(s1 + i) = f(m_array[child[0]], m_array[child[1]]);
            }
        }
    }

    T f(T a, T b){
        return a | b;
    }
    T get_dummy_value(){
        return 0;
    }

    void update(int i, T x){
        i += get_shift(m_depth - 1);
        m_array.at(i) = x;
        while(i > 0){
            i = get_parent_index(i);
            auto child = get_child_index(i);
            m_array.at(i) = f(m_array[child[0]], m_array[child[1]]);
        }
    }

    T query(int l, int r){
        return query(l, r, 0, 0, 1 << (m_depth - 1));
    }

    T query(int l, int r, int k, int l2, int r2){
        if (r2 <= l || r <= l2) return get_dummy_value();
        if (l <= l2 && r2 <= r) return m_array[k];
        else{
            auto v1 = query(l, r, 2 * k + 1, l2, (l2 + r2) / 2);
            auto v2 = query(l, r, 2 * k + 2, (l2 + r2) / 2, r2);
            return f(v1, v2);
        }
    }

    void print(){
        for(int d=0; d<m_depth; d++){
            auto s = get_shift(d);
            for(int i=0; i < (1<<d); i++){
                cout << m_array.at(s + i) << " ";
            }
            cout << endl;
        }
    }

private:
    int get_depth(int n){
        int msb = 32 - __builtin_clz(n);
        if(n == 1 << (msb-1)){
            return msb;
        }else{
            return msb + 1;
        }
    }

    int get_shift(int d){
        return (1 << d) - 1;
    }

    array<int, 2> get_child_index(int i){
        return array<int, 2>{
            2 * i + 1,
            2 * i + 2,
        };
    }
    int get_parent_index(int i){
        return (i - 1) / 2;
    }

public:
    size_t m_N;
    size_t m_depth;

    vector<T> m_array;
};

unsigned int encode_char(char c){
    return 1 << (c - 'a');
}

int main()
{
    int N, Q;
    string S;
    cin >> N >> S >> Q;

    vector<unsigned int> encode(N, 0);
    for(int i=0; i<N; i++){
        encode[i] = encode_char(S[i]);
    }
    SegmentTree<unsigned int> sg(encode);

    // Q
    vector<int> res;
    int qi;
    int iq, lq, rq;
    char cq;
    for(int i=0;i<Q;i++){
        cin >> qi;
        if(qi == 1){
            cin >> iq >> cq;
            iq--;
            auto e = encode_char(cq);
            sg.update(iq, e);
        }else{
            cin >> lq >> rq;
            lq--; rq--;
            auto ret = sg.query(lq, rq+1);
            auto n_unique = __builtin_popcount(ret);
            res.push_back(n_unique);
        }
    }
    for(auto v : res){
        cout << v << endl;
    }

    return 0;
}


Measured memory_bytes: 7044