#include <bits/stdc++.h>
#define FOR(i, a, b) for(int i=(a); i<(b); i++)
#define REP(i, n) FOR(i, 0, n)
#define all(x) (x).begin(), (x).end()
#define bit(x) (1L << (x))
using ll = long long;
using namespace std;

template<typename T>
vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
 
template<typename... Ts>
auto make_v(size_t a,Ts... ts){
        return vector<decltype(make_v(ts...))>(a,make_v(ts...));
}

template<class Monoid>
class SegmentTree{
private:
                using T = typename Monoid::T;
                const size_t n;
                vector<T> d;

                void build(){
                        for(size_t b = n - 1; b > 0; b--) d[b] = Monoid::op(d[b << 1], d[b << 1 | 1]);
                }

public:
                SegmentTree(size_t n)
                        : n(n), d(2 * n, Monoid::identify()) {}

                template<typename InputItr>
                        SegmentTree(InputItr first, InputItr last)
                        : n(distance(first, last)), d(2 * n, Monoid::identify()){
                                copy(first, last, next(d.begin(), n));
                                build();
                        }

                /* set one value */
                void modify(size_t k, T v){
                        for(d[k += n] = v; k > 1; k >>= 1) d[k >> 1] = Monoid::op(d[k], d[k ^ 1]);
                }

                /* return [l, r) value */
                T query(size_t l, size_t r){
                        T res {Monoid::identify()};
                        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
                                if (l&1) res = Monoid::op(res, d[l++]);
                                if (r&1) res = Monoid::op(res, d[--r]);
                        }
                        return res;
                }

                void dump(){
                        REP(i, 2 * n) {
                                //cout << i << " " << Monoid::print(d[i]) << endl;
                        }
                }
};

/* Range Sum Query */
template<typename U = ll>
struct RSQ{
        using T = U;
        static T op(const T& a, const T& b){ return a + b; };
        static constexpr T identify(){ return T(0); };
};

struct Element {
        static constexpr int M = 26;
        array<bool, M> table;
        
        constexpr Element() : table() {}

        constexpr Element(int i) : table() {
                table[i] = true;
        }

        constexpr int count() const {
                int c = 0;

                REP(i, M) c += table[i];

                return c;
        }

        static Element merge(const Element& a, const Element& b) {
                Element e;

                REP(i, M) {
                        e.table[i] = a.table[i] || b.table[i];
                }

                return e;
        }
};

struct Monoid {
        static constexpr int M = 26;
        using T = Element;

        static T op(const T& a, const T& b) {
                return T::merge(a, b);
        }

        static constexpr T identify() {
                return T();
        }
};

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

        int q;
        cin >> q;

        SegmentTree<Monoid> st(n);
        REP(i, n) {
                st.modify(i, Element(s[i] - 'a'));
        }

        REP(_, q) {
                int com;
                cin >> com;

                if (com == 1) {
                        int i;
                        char c;
                        cin >> i >> c;
                        
                        st.modify(i - 1, Element(c - 'a'));
                } else if (com == 2) {
                        int l, r;
                        cin >> l >> r;

                        auto ret = st.query(l - 1, r);
                        cout << ret.count() << endl;
                } else {
                        st.dump();
                }
        }

        return 0;
}


Measured memory_bytes: 26372