/// *********** Author: Olium_MdioxideN ***********

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define llu unsigned long long
#define i64 long long
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define ext exit(0)
#define fast ios_base :: sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define in_file freopen("hamming.in", "r", stdin)
#define out_file freopen("output.txt", "w", stdout)
#define newl printf("\n")
#define nl '\n'
#define endl '\n'
#define sci(x) scanf("%d",&(x))
#define sci2(x,y) scanf("%d %d",&(x),&(y))
#define scl(x) scanf("%lld",&(x))
#define scl2(x,y) scanf("%lld %lld",&(x),&(y))
#define pr printf
#define forr(i,b,e) for(int (i)=(b); (i) <= (e); (i)++)
#define fora(i,n) for(int (i)=0; (i) < (n); (i)++)
#define F first
#define S second
#define mset0(x) memset((x), 0, sizeof((x)));
#define mset1(x) memset((x), -1, sizeof((x)));
#define bs binary_search
#define all(x) (x).begin(),(x).end()
#define pqmin(x) priority_queue<x, vector<x>, greater<x> >
#define pqmax(x) priority_queue<x>
#define sortd(x) sort(all(x), greater<int>())
#define vi vector<int>
#define pii pair<int,int>
#define mpii map<int,int>
#define elif else if
#define debug(x) cerr << "Debug: " << x << '\n';
#define intmx INT_MAX
#define pi 3.14159265358979323846D
#define gcd(x,y) __gcd(x,y)
#define lcm(x,y) __lcm(x,y)
#define fact(x) factorial(x)
#define sieve(x) normal_sieve(x)
#define bsieve(x) bitwise_sieve(x)
#define bprime(x) !Chk(x)
#define runtime() cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n"
template <typename type> type __lcm(type n1,type n2){return n1*(n2/gcd(n1,n2));}
ll nCr(int n, int r)
{
    int f1 = r, f2 = n-r;
    if(f2 > f1) swap(f2,f1);
    ll result = 1;
    for(int i = 1; i <= f2; i++)
    {
        result *= (i+f1);
        result /= i;
    }
    return result;
}
ll nPr(int n, int r, ll mod = 0)
{
    ll result = 1;
    for(int i = n-r+1; i <= n; i++) {result *= i; if(mod) result %= mod;}
    return result;
}
ll factorial(int n, ll modulo = 0)
{
    if(n == 0) return 1;
    if(modulo) return (n*factorial(n-1))%modulo;
    else return n*factorial(n-1);
}

//implementation of normal sieve_of_eratosthenes
int *primes = NULL;
bool *isPrime = NULL;
int pidx = 0;
void normal_sieve(int n)
{
    n+=5;
    isPrime = new bool[n];
    memset(isPrime, 1, n);
    int sq = sqrt(n);
    isPrime[0] = isPrime[1] = false;
    for(int i = 4; i < n; i+=2) isPrime[i] = false;
    for(int i = 3; i <= sq; i+=2) if(isPrime[i]) for(int j = i*i; j < n; j+=(i<<1)) isPrime[j] = false;
    //comment out the rest to fast up the sieve for 10e7
    int primeCount = 1;
    for(int i = 3; i < n; i+=2) primeCount+=(isPrime[i]);
    primes = new int[primeCount];
    primes[pidx++] = 2;
    for(int i = 3; i < n; i+=2) if(isPrime[i]) primes[pidx++] = i;
}

//implementation of bitwise sieve_of_eratosthenes
int *isbPrime = NULL;
#define Set(n) (isbPrime[n>>5]=isbPrime[n>>5] or (1<<(n%32)))
#define Chk(n) (isbPrime[n>>5]&(1<<(n%32)))
void bitwise_sieve(int n)
{
    n+=5;
    int array_size = (n>>5);
    isbPrime = new int[array_size];
    memset(isbPrime, 0, n>>3);
    int sq = sqrt(n);
    Set(0); Set(1);
    for(int i = 4; i < 64; i+=2) Set(i);
    for(int i = 2; i < array_size; i++) isbPrime[i] = isbPrime[1];
    for(int i = 3; i <= sq; i+=2) if(!Chk(i)) for(int j = i*i; j < n; j+=(i<<1)) Set(j);
}

/// * * *    Main Code Starts Now    * * *

#define MOD 10000007
#define MAX 100010
void f();
int main()
{
    //sieve(MAX);
    fast;
    //in_file;
    //out_file;
    int t = 1;
    //sci(t);
    forr(i,1,t)
    {
        //printf("Case %d: ", i);
        f();
    }
    return 0;
}

string s;
int tree[2000010][26];

void init(int b, int e, int node)
{
    int mid = (b+e) >> 1, lft = node << 1, rgt = lft +1;
    if(b == e)
    {
        tree[node][s[b]-'a']++;
        return;
    }
    init(b, mid, lft);
    init(mid+1, e, rgt);
    for(int i = 0; i < 26; i++)
    {
        tree[node][i] = tree[lft][i] + tree[rgt][i];
    }
}

void update(int node, int b, int e, int poss, char c)
{
    int lft = node << 1, rgt = lft + 1, mid = (b+e) >> 1;
    if(b > poss || e < poss) return;
    if(b == poss && e == poss)
    {
        tree[node][s[b]-'a']--;
        s[b] = c;
        tree[node][s[b]-'a']++;
        return;
    }
    update(lft, b, mid, poss, c);
    update(rgt, mid+1, e, poss, c);
    for(int i = 0; i < 26; i++)
    {
        tree[node][i] = tree[lft][i] + tree[rgt][i];
    }
}
vector<int> dummy(26);
vector<int> query(int node, int b, int e, int st, int en)
{
    int lft = node << 1, rgt = lft + 1, mid = (b+e) >> 1;
    if(b > en || e < st) return dummy;
    if(b >= st && e <= en)
    {
        int cnt = 0;
        vector<int> ret(26);
        for(int i = 0; i < 26; i++)
        {
            ret[i] = tree[node][i];
        }
        return ret;
    }
    vector<int> ret1 = query(lft, b, mid, st, en);
    vector<int> ret2 = query(rgt, mid+1, e, st, en);
    for(int i = 0; i < 26; i++)
    {
        ret1[i] += ret2[i];
    }
    return ret1;
}
void f()
{
    for(int i = 0; i < 26; i++)
    {
        dummy[i] = 0;
    }
    int n;
    cin >> n;
    cin >> s;
    s = '|' + s;
    init(1, n, 1);
    int q;
    cin >> q;
    while(q--)
    {
        int ch;
        cin >> ch;
        if(ch == 1)
        {
            int poss;
            char up;
            cin >> poss >> up;
            update(1, 1, n, poss, up);
        }
        else
        {
            int l,r;
            cin >> l >> r;
            vector<int> ans;
            ans = query(1, 1, n, l, r);
            int cnt = 0;
            for(int i = 0; i < 26; i++)
            {
                if(ans[i] > 0) cnt++;
            }
            cout << cnt << nl;
        }
    }
}



Measured memory_bytes: 109488