/* #      157 - E                    */

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <deque>
#include <map>
#include <iomanip>
#include <bitset>
#include <functional>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <cstdint>
#include <cstring>
//#pragma warning(disable:4996)

using namespace std;


/** Type Define **/
typedef long long int           ll;
typedef pair<int, int>          pii;
typedef pair<ll, ll>            pll;
typedef vector<string>          vs;
typedef vector<bool>            vb;
typedef vector<int>             vi;
typedef vector<long long>		vl;
typedef vector<vi>              vvi;
typedef vector<vl>				vvl;
typedef vector<char>            vch;
#define		it(x)  x.begin() 
#define		all(x)  x.begin(), x.end()
#define		pb(x)   push_back(x)
constexpr int           inf = 0x3f3f3f3f;
constexpr long long 	INF = 9123456789123456789;
constexpr long long     MOD = 1000000007LL;

int OR(const int& x, const int& y) {
    return x | y;
}

int bitCount(const int& x) {
    if (x == 0)  return 0;
    else        return (x & 1) + bitCount(x >> 1);
}

template <typename M>
struct SegTree {
    using Op = function<M(const M&, const M&)>;
    M ID;   // monoid identity
    Op op;  // associative operation
    int N;  // 2^lg space, for non-commutative
    vector<M> a;

    SegTree(int n, M leaf_default, M _ID, Op _op) : ID(_ID), op(_op) {
        init_space(n);
        fill(a.begin() + N, a.begin() + N + n, leaf_default);
        build();
    }

    SegTree(const vector<M> leaves, M _ID, Op _op) : ID(_ID), op(_op) {
        int n = leaves.size();  // array size
        init_space(n);          // Initialize Segment Tree by ID(0)
        copy(leaves.begin(), leaves.end(), a.begin() + N);
        build();                // Build up Segment Tree.
    }

    void init_space(int n) {
        N = 1; while (N < n) N <<= 1; // assign array space
        a.assign(N << 1, ID);         // 0으로 초기화
       /* cout << "n : " << n
            << "\nN : " << N
            << "\nN<<1 : " << (N << 1) << endl;*/
    }

    inline void pull(int i) { a[i] = op(a[i << 1], a[i << 1 | 1]); }
    void build() { for (int i = N - 1; i >= 1; i--) pull(i); }

    //Update
    void assign(int p, M val) {
        assert(0 <= p && p < N);

        //Root Node까지 올라가며 차례로 갱신
        for (a[p += N] = val; p >>= 1;) pull(p);
    }

    //Query
    M query(int l, int r) const {
        assert(0 <= l && r < N);
        M resl(ID), resr(ID);

        for (l += N, r += N; l <= r; l >>= 1, r >>= 1) {
            //cout << "l : " << l << ", " << "r : " << r << endl;
            if (l & 1) resl = op(resl, a[l++]);
            if (!(r & 1)) resr = op(a[r--], resr);
        }
        int ans = op(resl, resr);
        //cout << bitset<32>(ans) << endl;
        return ans;
    }
    M query_point(int p) const {
        assert(0 <= p && p < N);
        return a[p + N];
    }
    M query_all() const { return a[1]; }
};

void solve() {
    int n; cin >> n;
    string s; cin >> s;
    vector<int> a(n);

    for (int i = 0; i < n; i++) {
        a[i] = 1 << (s[i] - 'a'); // transform to [0, 25].
    }

    SegTree<int> occur(a, 0, [](int u, int v) { return u | v; });

    int q; cin >> q; //the number of quries.
    while (q--) {
        int op; cin >> op;
        if (op == 1) { //change i-th character.
            int i; char x;
            cin >> i >> x;
            i--;
            occur.assign(i, 1 << (x - 'a'));
        }
        else {  //the number of different characters in [l, r].
            int l, r;
            cin >> l >> r;
            l--; r--;
            cout << bitCount(occur.query(l, r)) << '\n';
        }
    }
}



int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    return 0;
}

Measured memory_bytes: 8860