#include <iostream>
#include <cassert>
#include <vector>
#include <algorithm>
#include <climits>

#include <stack>
#include <queue>
// #include <deque>
// #include <set>
// #include <map>
// #include <string>
// #include <unordered_set>
// #include <unordered_map>

#include <tuple>
// #include <cmath>
// #include <numeric>

using namespace std;


typedef long long ll;
typedef pair<long,long> pll;
typedef pair<int,int> pii;
typedef pair<int,long> pil;
typedef pair<long,int> pli;
typedef pair<long long, long long> pllll;
typedef pair<long long, int> plli;
typedef pair<int,long long> pill;
typedef vector<vector<long long>> vvll;
typedef vector<vector<long>> vvl;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<long> vl;
typedef vector<long long> vll;

#define emplace_back pb
const char el = '\n';

//2^20 = 2*524288 >= 2*n;
int a[1048576][27];
int N;
int root = 1;
int leftend[1048576];
int rightend[1048576];
//for a node NODE, a[NODE][3] counts how many 'd's appear in the range represented by the node;
//a[NODE][26] always stores the number of unique charactesr;

/*
Edge cases:


*/
int build(string& s, int n) {

    int uniq = 0;
    vector<int> temp(27);

    for (int i = N; i<N+N; ++i) 
    {
        if (i-N < n) ++a[i][ s[i-N]- 'a'];
        if (i-N < n) a[i][26]=1;
        leftend[i] = i-N;
        rightend[i] = i-N+1;
    }

    for (int i = N-1; i>=1; --i) {
        leftend[i] = leftend[2*i];
        rightend[i] = rightend[2*i+1];
        for (int ch=0; ch<26; ++ch) {

            int prev = a[i][ch];
            a[i][ch] += a[2*i][ch];


            a[i][ch] += a[2*i+1][ch];

            if (a[i][ch]>0) ++a[i][26];
        }


    }

    // cout<<"n="<<n<<", N="<<N<<endl;
    // for (int i = N+n; i>=1; --i) {
    //     cout<<"node:  "<<i<<";   ";
    //     cout<<"has endpoints "<<leftend[i]<<" and "<<rightend[i]<<endl;
    //     cout<<"for substring "<<s.substr(leftend[i],rightend[i]-leftend[i])<<" we found "<<a[i][26]<<" uniques"<<endl;
    // }
}

vector<int> mrg(vector<int>& a, vector<int>& b) {
    vector<int> ret(27,0);
    int numuniq = 0;
    for (int i = 0; i<26; ++i) {
        ret[i] = a[i]+b[i];
        if (ret[i]>0) ++numuniq;
    }
    ret[26]=numuniq;
    return ret;
}
vector<int> rquery(string& s, int node, int i, int j) {
    //returns a frequency map of all letters appearing in the range [l,r)
    //including a last character containing the number of uniques;

    int l = leftend[node], r = rightend[node];

    // cout<<"querying at node ["<<l<<","<<r<<") for range "<<"["<<i<<","<<j<<")"<<el;
    if (l==i && r==j) {
        vector<int> ret(a[node],a[node]+27);
        // cout<<"found matching node:  "<<"result has length "<<ret.size()<<" and equals ";
        // for (auto x: ret) cout<<x<<" ";
        // cout<<el;
        return ret;
    }

    //node = [l,r) and [i,j) are disjoint
    if (j<=i || r<=i || l>=j) {
        return vector<int>(27,0);
    }

    int med = (l+r)/2;
    // cout<<'\t'<<"doing recursive calls at nodes ";
    // cout<<leftend[2*node]<<","<<rightend[2*node]<<" and ";
    // cout<<leftend[2*node+1]<<","<<rightend[2*node+1]<<el;
    auto leftchildquery = rquery(s,node*2,max(i,l),min(j,med));
    auto rightchildquery = rquery(s,node*2+1,max(i,med),min(j,r));

    return mrg(leftchildquery,rightchildquery);




}


int query(string& s, int l, int r) {
    auto v = rquery(s, root,l,r);
    return v[26];
}



void update(string& s, int i, char ch) {
    int newcharstat = (int) (ch-'a');
    int origcharstat = (int) (s[i] - 'a');

    if (origcharstat == newcharstat) return;
    //propagate the change upward
    //node representing singleton range {i} is N+i;
    --a[N+i][origcharstat];
    ++a[N+i][newcharstat];
    //a[N+i][26] is unchanged; it's always 1;

    int node = (N+i)/2;

    while (node>=1) {
        --a[node][origcharstat];
        ++a[node][newcharstat];
        if (a[node][newcharstat]==1) {
            ++a[node][26];
        }
        if (a[node][origcharstat]==0) {
            --a[node][26];
        }
        node /= 2;
    }
}


int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    int n; cin>>n; cin.ignore();
    N = 1;
    while (N<n) {
        N*=2;
    }
    string s; cin>>s; cin.ignore();

    build(s,n);
    int q; cin>>q; cin.ignore();

    for (int t=0; t<q; ++t) {
        int querytype, left, right;
        int i; char ch;
        cin>>querytype;
        if (querytype==1) {
            cin>>i>>ch;
            --i;
            update(s,i,ch);
            s[i]=ch;
            // cout<<"after update, s is now "<<s<<el;
        } else {
            assert(querytype==2);

            cin>>left>>right;
            --left;
            auto x = query(s,left,right);
            cout<<x<<el;
        }
    }




}

Measured memory_bytes: 117660