#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define loop(i,a,b) for (ll i=a; i<b; ++i)

// Using https://www.geeksforgeeks.org/binary-indexed-tree-range-updates-point-queries/
  
// Updates a node in Binary Index Tree (BITree) at given index 
// in BITree. The given value 'val' is added to BITree[i] and 
// all of its ancestors in tree. 
void updateBIT(ll BITree[], ll n, ll index, ll val) 
{ 
    // index in BITree[] is 1 more than the index in arr[] 
    index = index + 1; 
  
    // Traverse all ancestors and add 'val' 
    while (index <= n) 
    { 
        // Add 'val' to current node of BI Tree 
        BITree[index] += val; 
  
        // Update index to that of parent in update View 
        index += index & (-index); 
    } 
} 
  
// Constructs and returns a Binary Indexed Tree for given 
// array of size n. 
ll *constructBITree(ll arr[], ll n) 
{ 
    // Create and initialize BITree[] as 0 
    ll *BITree = new ll[n+1]; 
    for (ll i=1; i<=n; i++) 
        BITree[i] = 0; 
  
    // Store the actual values in BITree[] using update() 
    for (ll i=0; i<n; i++) 
        updateBIT(BITree, n, i, arr[i]); 
  
    // Uncomment below lines to see contents of BITree[] 
    //for (ll i=1; i<=n; i++) 
    //      cout << BITree[i] << " "; 
  
    return BITree; 
} 
  
// SERVES THE PURPOSE OF getElement() 
// Returns sum of arr[0..index]. This function assumes 
// that the array is preprocessed and partial sums of 
// array elements are stored in BITree[] 
ll getSum(ll BITree[], ll index) 
{ 
    ll sum = 0; // Iniialize result 
  
    // index in BITree[] is 1 more than the index in arr[] 
    index = index + 1; 
  
    // Traverse ancestors of BITree[index] 
    while (index>0) 
    {
        // Add current element of BITree to sum 
        sum += BITree[index]; 
  
        // Move index to parent node in getSum View 
        index -= index & (-index); 
    } 
    return sum; 
} 
  
// Updates such that getElement() gets an increased 
// value when queried from l to r. 
void update(ll BITree[], ll l, ll r, ll n, ll val) 
{ 
    // Increase value at 'l' by 'val' 
    updateBIT(BITree, n, l, val); 
  
    // Decrease value at 'r+1' by 'val' 
    updateBIT(BITree, n, r+1, -val); 
} 
  
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll N,Q; string S;
    cin >> N >> S >> Q;
    ll arr[N];
    loop(i,0,N) arr[i]=0; 
    vector <ll*> BITrees(26); 
    loop(i,0,26) BITrees[i] = constructBITree(arr, N); 
    loop(i,0,N)
    {
        int index = S[i]-'a';
        update(BITrees[index], i, N-1, N, 1);
    }
    while (Q--)
    {
        int type;
        cin >> type;
        if (type == 1)
        {
            int pos; char chr;
            cin >> pos >> chr;
            pos--;
            update(BITrees[S[pos]-'a'], pos, N-1, N, -1);
            update(BITrees[chr-'a'], pos, N-1, N, 1);
            S[pos]=chr;
        }
        if (type == 2)
        {
            ll l,r;
            cin >> l >> r;
            l--; r--;
            ll ans=0;
            loop(i,0,26)
            {
                if (l>0) ans += (getSum(BITrees[i], r) - getSum(BITrees[i], l-1) > 0); 
                else ans += (getSum(BITrees[i], r) > 0);
            }
            cout << ans << "\n";
        }
    }
    return 0;
}

Measured memory_bytes: 106396