#include <bits/stdc++.h>
using namespace std;
typedef long long int llint;
typedef unsigned long long int ullint;
std::string YesNo[] = {"No","Yes"};
#define loop(i,N) for(int i=0; i<(N); i++)
template<typename T>
auto sort_all(T& v) { return std::sort(v.begin(),v.end()); }
template<typename T>
auto sum_all(const T& v) { auto z = v[0]; z = 0;
    return std::accumulate(v.begin(),v.end(),z); }
template<typename T>
auto input( std::size_t N,
            const std::vector<T>& head={},
            const std::vector<T>& tail={}) {
    auto s = head.size();
    auto t = tail.size();
    std::vector<T> v;
    v.reserve(s+N+t);
    v.insert(v.end(), head.begin(), head.end());
    v.resize(s+N);
    loop(i,N) std::cin >> v[s+i];
    v.insert(v.end(), tail.begin(), tail.end());
    return std::move(v);
}
class range {
    typedef int Int;
    Int start, stop, step;
    void initialize() {
        auto sign = (step >= 0) ? 1 : -1;
        stop = start + ((stop-start-sign)/step + 1) * step;
        if ((stop-start) * step <= 0) stop = start;
    }
public:
    range(Int start, Int stop, Int step=1) : start(start), stop(stop), step(step) {
        initialize();
    }
    range(Int stop) : start(0), stop(stop), step(1) { initialize(); }
    struct iterator {
        Int i, step;
        Int& operator*() { return i; }
        iterator& operator++() { i += step; return *this; }
        bool operator!=(const iterator& v) { return i != v.i; }
    };
    iterator begin() { return {start, step}; }
    iterator end()   { return {stop, step}; }
};
template<typename T1, typename T2>
std::pair<T1,T2> operator-(const std::pair<T1,T2>& x)
{
    return std::make_pair(-x.first, -x.second);
}
template<typename T1, typename T2>
std::pair<T1,T2> operator+(
    const std::pair<T1,T2>& x,
    const std::pair<T1,T2>& y)
{
    return std::make_pair(x.first+y.first, x.second+y.second);
}
template<typename T1, typename T2>
std::pair<T1,T2> operator-(const std::pair<T1,T2>& x, const std::pair<T1,T2>& y)
{
    return x + (-y);
}
template<typename T1, typename T2>
std::pair<T1,T2>& operator+=(std::pair<T1,T2>& x, const std::pair<T1,T2>& y)
{
    x.first += y.first;
    x.second += y.second;
    return x;
}
template<typename T1, typename T2>
std::pair<T1,T2>& operator-=(std::pair<T1,T2>& x, const std::pair<T1,T2>& y)
{
    return x += (-y);
}
template<typename T1, typename T2>
std::ostream& operator<<(std::ostream& cout, const std::pair<T1,T2>& data)
{
    cout << "(" << data.first << ", " << data.second << ")";
    return cout;
}
template<typename T>
std::ostream& operator<<(std::ostream& cout, const std::vector<T>& data)
{
    cout << "[";
    if (data.size() == 0) {}
    else if (data.size() == 1) { cout << data[0]; } 
    else {
        cout << data[0];
        for (auto itr=data.begin()+1; itr!=data.end(); ++itr) {
            cout << ", " << *itr;
        }
    }
    cout << "]";
    return cout;
}

int bitlen(unsigned long long int n)
{
    int total = sizeof(n) * 8;
    int l = total, r = -1, mid;
    while (l > r+1) {
        mid = (l+r)/2;
        if (n >> mid == 0) {
            l = mid;
        } else {
            r = mid;
        }
    }
    return l;
}
template<typename T>
class SegmentTree
{
private:
//public:
    int N;
    T nullret = T(-1);
    std::vector<int> node;
    std::vector<T> data;
    std::function<bool(T,T)> lessthan;
    bool reverse;

public:
    bool comp(int i, int j)
    {
        if (j < 0) {
            return true;
        } else if (i < 0) {
            return false;
        } else {
            auto ret = lessthan(data[i], data[j]);
            if (reverse) { ret = !ret; }
            return ret;
        }
    }

    SegmentTree(std::size_t N_,
                const std::vector<T>& data_ = std::vector<T>(0),
                bool reverse = false,
                std::function<bool(T,T)> lessthan = [](T a, T b){ return a <= b; }
                ) : data(data_), node(0), lessthan(lessthan), reverse(reverse)
    {
        int M = std::max(data.size(), N_);
        N = 1 << std::max(bitlen(M)-1, 0);
        if (N < M) N *= 2;
        node.resize(2*N-1,-1);
        for (auto i=0; i<data.size(); i++) {
            node[N-1+i] = i;
        }
        if (data.size() < N) { data.resize(N,T(0)); }
        for (auto i=N-2; i>=0; i--) {
            auto left_i = node[2*i+1], right_i = node[2*i+2];
            node[i] = this->comp(left_i, right_i) ? left_i : right_i;
        }
    }

    void setnull(const T& t) { return nullret = t; }

    const T& at(int i) { return data[i]; }

    void update(int n, const T& v) {
        data[n] = v;
        int i = N - 1 + n;
        node[i] = n;
        while (i > 0) {
            i = (i-1)/2;
            auto left_i = node[2*i+1], right_i = node[2*i+2];
            auto new_i = comp(left_i, right_i) ? left_i : right_i;
            if (new_i == node[i] && new_i != n) {
                break;
            } else {
                node[i] = new_i;
            }
        }
    }

    void emptify(int n) {
        int i = N - 1 + n;
        node[i] = -1;
        while (i > 0) {
            i = (i-1)/2;
            auto left_i = node[2*i+1], right_i = node[2*i+2];
            auto new_i = comp(left_i, right_i) ? left_i : right_i;
            if (new_i == node[i] && new_i != n) {
                break;
            } else {
                node[i] = new_i;
            }
        }
    }

    const T& query(int l=0, int r=-1) {
        auto s = query_index(l, r);
        if (s < 0) { return nullret; } else { return data[s]; }
    }

    int query_index(int l=0, int r=-1) {
        if (r < 0) r = N;
        int L = l + N, R = r + N;
        int s = -1;
        while (L < R) {
            if (R & 1) {
                R -= 1;
                if (comp(node[R-1], s)) s = node[R-1];
            }
            if (L & 1) {
                if (comp(node[L-1], s)) s = node[L-1];
                L += 1;
            }
            L >>= 1; R >>= 1;
        }
        return s;
    }
};

typedef llint Int;

int main(void)
{
    unsigned int N, Q;
    string S;
    cin >> N >> S >> Q;
    vector<SegmentTree<int>> sg(26, SegmentTree<int>(N));
    // loop(i,4) cout << sg[i].data << " " << sg[i].node << endl;
    for (auto i: range(N)) {
        sg[int(S[i]-'a')].update(i,0);
    }
    // cout << 0 << endl;
    // return 0;
    // loop(i,4) cout << sg[i].data << " " << sg[i].node << endl;
    //cout << "abc" << endl;
    //cout << N << " " << S << " " << Q << endl;

    for (auto q: range(Q)) {
        int k;
        cin >> k;
        //cout << k << " " << s << " " << t << endl;
        //cout << "k=" << k << endl;
        if (k == 1) {
            int i; char c;
            cin >> i >> c;
            //cout << i;
            i--;
            if (S[i] != c) {
                sg[int(c-'a')].update(i,0);
                sg[int(S[i]-'a')].emptify(i);
                S[i] = c;
            }
        } else {
            int l, r;
            cin >> l >> r;
            l--;
            int ans = 0;
            for (auto c: range(26)) {
                if (sg[c].query(l,r) >= 0) {
                    ans += 1;
                }
            }
            cout << ans << endl;
        }
    }

    return 0;
}

Measured memory_bytes: 166916