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

#define debug(x) cout <<"DEBUG"<<" "<< #x << ":" << x << '\n'

// n回繰り返し
#define rep(i,n) for(int i = 0; i < ((int)(n)); i++)   // 0-indexed昇順
#define rep1(i,n) for(int i = 1; i <= ((int)(n)); i++) // 1-indexed昇順
#define rrep(i,n) for(int i = ((int)(n)-1); i >= 0; i--)  // 0-indexed降順
#define rrep1(i,n) for(int i = ((int)(n)); i >= 1; i--)   // 1-indexed降順
#define all(x) (x).begin(),(x).end()

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<vi> vii;  // 2次元配列
typedef vector<ll> vll;
typedef vector<double> vd;
typedef pair<int, int> PII;

template<typename T>
using vec = vector<T>;
template<class T>
using maxheap = std::priority_queue<T>;
template<class T>
using minheap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template<class T,class U> inline bool chmax(T &a, const U &b){if(a<b){a=b;return 1;}return 0;}
template<class T,class U> inline bool chmin(T &a, const U &b){if(a>b){a=b;return 1;}return 0;}

const ld Pi = std::acos(-1.0L);
const ll infll = (1LL<<62)-1;
const int inf = (1<<30)-1;
const int mod = 1000000007;
// const int mod = 998244353;

/* Segment Tree -----------*/
template <typename M>
class SegmentTree {
    using F = std::function< M(M, M) >;
private:
    int n;
    F func;
    M M_init;
    std::vector<M> t;
public:
    // constructor
    SegmentTree(int &n, F func, const M &M_init): n(n), func(func), M_init(M_init) { t.assign(2*n, M_init); }
    SegmentTree(std::vector<M> &vec, F func, const M &M_init): n(vec.size()), func(func), M_init(M_init) {
        t.assign(2*vec.size(), M_init);
        for(int i = 0; i < vec.size(); ++i) t[i+vec.size()] = vec[i];
    }

    void build() {  // build segment tree
        for(int i = n-1; i > 1; --i) t[i] = func(t[i<<1], t[i<<1|1]);
    }
    void modify(int p, M val) {  // update value at position p
        for(t[p += n] = val; p > 1; p >>= 1) t[p>>1] = func(t[p], t[p^1]);
    }
    M query(int l, int r) {  // reply to query [l, r)
        M resl = M_init, resr = M_init;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) resl = func(resl, t[l++]);
            if(r & 1) resr = func(t[--r], resr);
        }
        return func(resl, resr);
    }
    M operator[](const int &k) const {return t[k+n];}  // mustn't use to input
};


/*FUNCs=================================================*/


/*MAIN==================================================*/
signed main(){
    int _StartTime_ = clock();
    cin.tie(nullptr);
    ios::sync_with_stdio(false);   //cin cout 高速化
    // cout << fixed << setprecision(15);

    int n; cin >> n;
    string s; cin >> s;

    vi bit_set(s.size());
    for (int i = 0; i < n; ++i) {
        int p = (int)(s[i]-'a');
        bit_set[i] |= (1<<p);
    }
//    for(auto i : bit_set) cout << i << '\n';

    SegmentTree<int> BitSet(bit_set, [](int a, int b){ return (a|b); }, 0);
    BitSet.build();

//    reply to query
    int q; cin >> q;
    rep(_,q) {
        int TYPE; cin >> TYPE;
        if (TYPE==1) {
            int i; cin >> i; char c; cin >> c;
            int ch = (int)(c-'a');
            if(BitSet[i-1] == (1<<ch)) continue;
            BitSet.modify(i-1, (1<<ch));
        }
        else {
            int l, r; cin >> l >> r;
            int bit = BitSet.query(l-1, r);
            int ans = 0;
            while(bit > 0) {
                ans += (bit&1);
                bit >>= 1;
            }
            cout << ans << '\n';
        }
    }

    // printf("ExcutionTime: %d /ms\n",1000*(int)((clock()-_StartTime_)/CLOCKS_PER_SEC));
}

Measured memory_bytes: 6812