Problem:
Score : 500 points

Problem Statement

You are given a string S of length N consisting of lowercase English letters.

Process Q queries of the following two types:

Type 1: change the i_q-th character of S to c_q. (Do nothing if the i_q-th character is already c_q.)

Type 2: answer the number of different characters occurring in the substring of S between the l_q-th and r_q-th characters (inclusive).

Constraints

N, Q, i_q, l_q, and r_q are integers.

S is a string consisting of lowercase English letters.

c_q is a lowercase English letter.

1 \leq N \leq 500000

1 \leq Q \leq 20000

|S| = N

1 \leq i_q \leq N

1 \leq l_q \leq r_q \leq N

There is at least one query of type 2 in each testcase.

Input

Input is given from Standard Input in the following format:

N
S
Q
Query_1
\vdots
Query_Q

Here, Query_i in the 4-th through (Q+3)-th lines is one of the following:

1 i_q c_q

2 l_q r_q

Output

For each query of type 2, print a line containing the answer.

Sample Input 1

7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7

Sample Output 1

3
1
5

In the first query, cdbb contains three kinds of letters: b , c , and d, so we print 3.

In the second query, S is modified to abcdzbd.

In the third query, a contains one kind of letter: a, so we print 1.

In the fourth query, S is modified to abcazbd.

In the fifth query, S does not change and is still abcazbd.

In the sixth query, abcazbd contains five kinds of letters: a, b, c, d, and z, so we print 5.

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

/*
    Author:zeke
    
    pass System Test!
    GET AC!!
*/
#include <iostream>
#include <queue>
#include <vector>
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <algorithm>
#include <functional>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <map>
#include <iomanip>
#include <utility>
#include <stack>
#include <bitset>
using ll = long long;
using ld = long double;
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(), (x).end()
#define rep3(var, min, max) for (ll(var) = (min); (var) < (max); ++(var))
#define repi3(var, min, max) for (ll(var) = (max)-1; (var) + 1 > (min); --(var))
#define Mp(a, b) make_pair((a), (b))
#define F first
#define S second
#define int ll
#define Icin(s) \
    ll(s);      \
    cin >> (s);
#define Scin(s) \
    ll(s);      \
    cin >> (s);
template <class T>
bool chmax(T &a, const T &b)
{
    if (a < b)
    {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T &a, const T &b)
{
    if (b < a)
    {
        a = b;
        return 1;
    }
    return 0;
}
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<V> VV;
typedef vector<P> VP;
ll MOD = 1e9 + 7;
ll INF = 1e18;
VV value; // ノードの値を持つ配列
ll N;             // 葉の数

void update(ll moji,ll i,ll dis)
{
    // i 番目の葉の値を x に変える
    i += N - 1; // i 番目の葉のノード番号
    value[moji][i]+=dis;
    while (i > 0)
    {
        i = (i - 1) / 2; // ノード i の親ノードの番号に変える
        value[moji][i] += dis;
    }
}

int query(ll moji,int a, int b, int k, int l, int r)
{
    // [a, b) の区間に対するクエリについて
    // ノード k （区間 [l, r) 担当）が答える
    if (r <= a || b <= l)
        return 0; // 区間が被らない場合は INF を返す
    if (a <= l && r <= b)
        return value[moji][k]; // ノード k の担当範囲がクエリ区間 [a, b)
                         // に完全に含まれる
    else
    {
        int c1 = query(moji,a, b, 2 * k + 1, l, (l + r) / 2); // 左の子に値を聞く
        int c2 = query(moji,a, b, 2 * k + 2, (l + r) / 2, r); // 右の子に値を聞く
        return c1+c2;                              // 左右の子の値の min を取る
    }
}
int n, q;
void test(){
    rep(i,n){
        rep(j,26){
            if(query(j,i,i+1,0,0,N)){
                cout<<(char)(j+'a');
            }
            
        }
        cout<<endl;
    }
    cout<<endl;
}
signed main(void)
{
    
    cin >> n;
    string s;
    cin>>s;
    N = 1;
    while (N <= n){
        N *= 2; // 葉の数を計算（n以上の最小の2冪数）
    }
    VV temp(27,V(4*N-1,0));
    value=temp;
    rep(i,n){
        char c=s[i];
        ll moji=c-'a';
        update(moji,i,1);
    }
    
    cin>>q;
    rep(i,q){
        int type;
        cin>>type;
        if(type==1){
            ll x;
            char c;
            cin>>x;
            cin>>c;
            x--;
            char changec=s[x];
            ll moji=c-'a';
            ll cmoji=changec-'a';
            update(moji,x,1);
            update(cmoji,x,-1);
         //   cout<<c<<" "<<changec<<endl;
        }else{
          //  test();
            ll x,y;
            cin>>x>>y;
            x--;y--;
            ll sum=0;
            rep(i,26){
                if(query(i,x,y+1,0,0,3*N)>=1){
                  //  cout<<(char)(i+'a')<<" ";
                    sum++;
                }
            }
            cout<<sum<<endl;
        }
    }
    
   /* rep(i,n){
        rep(j,26){
            if(query(j,i,i+1,0,0,N)){
                cout<<(char)(j+'a');
            }
            
        }
        cout<<endl;
    }
    cout<<endl;*/
    
}