#include <bits/stdc++.h>


using namespace std;

/* macros */
#define all(v)			((v).begin()), ((v).end())
#define SIZE(v)			((int)((v).size()))
#define LOG(x)			log((double)x)
#define TOLOWER(x)          transform(all(x),x.begin(),::tolower)
#define TOUPPER(x)          transform(all(x),x.begin(),::toupper)
#define ROUND(x,m)			(round((double)x/m)*m)
#define DIGITS(x)			(floor(log10((double)x))+1)
#define READSTR(x)			getline(cin,x)
#define sort_g(a,b)              sort(a, b, greater<int>());
#define IOS() ios_base::sync_with_stdio(0);cin.tie(NULL);
#define REP(i, n) for (int i = 0; i < n; i++)
#define FILE_INPUT() 	freopen( "input.txt", "r", stdin)
#define FILE_OUTPUT()   freopen( "output.txt", "w", stdout)

/*typedefs*/
typedef long long ll;
/*functions*/
bool myCmp(pair<int,int> &p1 , pair<int,int>&p2)
{
    return p1.first > p2.first;
}
unsigned long long
choose(unsigned long long n, unsigned long long k) {
    if (k > n) {
        return 0;
    }
    unsigned long long r = 1;
    for (unsigned long long d = 1; d <= k; ++d) {
        r *= n--;
        r /= d;
    }
    return r;
}
int toInt(string str) {
    int num;
    istringstream iss(str); //put string in input stream
    iss>>num; return num; //read from stream as integer
}

template <class T> string toStr(T par) {
    ostringstream oss;  //output stream string
    oss<<par;    //write par to the stream
    return oss.str(); //return string of output
}

const int MAXN = 6*10e5;
int pre[MAXN][26] = {0};
int wak[MAXN];
map<int,pair<char,char>> inserted;

int main() {
    IOS();

    int n,t;
    string s;
    int q;
    cin>>n;
    cin>>s;
    cin>>q;

    //to include index 0 check 1
    for(int i = 1  ; i <= s.size() ; ++i)
    {
        for(int j =0 ; j < 26 ;j++)
        {
            //   pre[i] = pre[i-1] | (1<<(s[i-1]-'a'));
            pre[i][j] = pre[i-1][j];
        }
        pre[i][s[i-1]-'a']++;
    }

    while(q--)
    {
        cin>>t;
        if(t == 1)
        {
            //modfiy
            int idx;
            char c;
            cin>>idx>>c;
            idx--;
            if(inserted.find(idx) == inserted.end())
            {
                if(c == s[idx]) continue;
            }
            else
            {
                if(c == inserted[idx].first) continue;
            }

            inserted[idx] = make_pair(c,s[idx]);
        }
        else
        {
            //answer
            //check all inserted and removed char in between
            int ans = 0;
            int l , r;
            cin>>l>>r;
            l--;
            r--;
            if(l == r)
            {
                cout<<1<<endl;
                continue;
            }
            auto lb = inserted.lower_bound(l);
            int temp_alpha[26] = {0};
            for(int kk = 0 ; kk <26 ;++kk) temp_alpha[kk] =0;
            //if found and the found element is less than or equal r
            if((lb != inserted.end()) && (lb->first <= r))
            {

                //find elements strictlly larger than r
                auto ub = inserted.upper_bound(r);
                //this is the last element we don't want to access

                r++;

                //temp 26 array with modifications
                for(auto it = lb ; it != ub ; it++)
                {
                    temp_alpha[it->second.first-'a']++;
                    temp_alpha[it->second.second-'a']--;
                }
            }
            else
            {
                r++;
            }
            for(int i = 0 ; i < 26 ;++i)
                ans += ((pre[r][i]+temp_alpha[i])>pre[l][i]);

            cout<<ans<<endl;
        }
    }

    //difference in pop count is the number

    return 0;
}


Measured memory_bytes: 54940