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: Runtime Error)

#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<(n); ++i)
#define rep2(i, s, n) for(int i=s; i<(n); ++i)
#define ALL(v) (v).begin(), (v).end()

using namespace std;

typedef long long ll;

static const int INTINF = (2147483647 >> 1); // 10^9 + 5000
static const ll LLINF = (9223372036854775807 >> 1);
static const int MAX = 1e5+1;
static const ll MOD = 1e9+7;

namespace Kunitaka{
    template<
        typename TYPE,
        std::size_t SIZE
    >
    std::size_t array_length(const TYPE (&array)[SIZE])
    {
        return SIZE;
    }
}
using namespace Kunitaka;
namespace Printer{
    void br(){
        cout << endl;
    }

    void loop_cnt(int i){
        cout << "i = " << i << endl;
    }

    void loop_cnt(int i, int j){
        cout << "i = " << i << ", " << "j = " << j << endl;
    }

    template<class T>
    void print(T x){
        cout << x << endl;
    }

    template<class T, class S>
    void print(T x, S y){
        cout << x << "," << y << endl;
    }

    template<class T, class S, class U>
    void print(T x, S y, U z){
        cout << x << "," << y << "," << z << endl;
    }

    template<class T, class S>
    void print(pair<T, S> p){
        cout << p.first << ", " << p.second << endl;
    }

    template<
        typename TYPE,
        std::size_t SIZE
    >
    void print(const TYPE (&array)[SIZE]){
        int lim = array_length(array);
        for(int i=0; i<lim; i++){
            if(i) cout << " ";
            cout << array[i];
        }
        cout << endl;
    }

    template<class S>
    void print(vector<S> v){
        for(int i=0; i<v.size(); i++){
            if(i) cout << " ";
            cout<< v[i];
        }
        cout << endl;
    }

    template<class S>
    void print(vector<vector<S> > vv){
        for(int i=0; i<vv.size(); i++){
            for(int j=0; j<vv[i].size(); j++){
                if(j) cout << " ";
                cout << vv[i][j];
            }
            cout << endl;
        }
    }

    void yesno(bool x){
        if(x) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
};
using namespace Printer;

class LazySegmentTree {
    private:
        ll INTINF = 2147483647 >> 1; // 2147483647 >> 1
        ll n;
        vector<vector<ll> > node, lazy;
        vector<bool> lazyFlag;
        bool isMax = false;

    public:
        void init(vector<vector<ll> > v) {
            ll sz = v.size();
            n = 1; while(n < sz) n *= 2;
            vector<ll> tmp(30);
            node.resize(2*n-1, tmp);
            lazy.resize(2*n-1, tmp);
            lazyFlag.resize(2*n-1, false);

            for(ll i=0; i<sz; i++) node[i+n-1] = v[i];
            for(ll i=n-2; i>=0; i--) node[i] = compare(node[i*2+1], node[i*2+2]);
        }

        // k 番目のノードについて遅延評価を行う
        void lazyEvaluate(ll k, ll l, ll r) {
            if(lazyFlag[k]) {
                node[k] = lazy[k];
                if(r - l > 1) {
                    lazy[k*2+1] = lazy[k*2+2] = lazy[k];
                    lazyFlag[k*2+1] = lazyFlag[k*2+2] = true;
                }
                lazyFlag[k] = false;
            }
        }

        // 遅延評価を考慮した区間更新：[a, b)をxに更新
        void update(ll a, ll b, vector<ll> x, ll k=0, ll l=0, ll r=-1) {
            if(r < 0) r = n;
            lazyEvaluate(k, l, r);
            if(b <= l || r <= a) return;
            if(a <= l && r <= b) {
                lazy[k] = x;
                lazyFlag[k] = true;
                lazyEvaluate(k, l, r);
            }
            else {
                update(a, b, x, 2*k+1, l, (l+r)/2);
                update(a, b, x, 2*k+2, (l+r)/2, r);
                node[k] = compare(node[2*k+1], node[2*k+2]);
            }
        }

        // [a, b)の最小値を検索
        vector<ll> find(ll a, ll b, ll k=0, ll l=0, ll r=-1) {
            if(r < 0) r = n;
            lazyEvaluate(k, l, r);
            if(b <= l || r <= a) {
                vector<ll> tmp(30);
                return tmp;
            }
            if(a <= l && r <= b) return node[k];
            vector<ll> vl = find(a, b, 2*k+1, l, (l+r)/2);
            vector<ll> vr = find(a, b, 2*k+2, (l+r)/2, r);
            return compare(vl, vr);
        }

        vector<ll> getNode(ll index){
            return node[index + n / 2];
        }

        vector<ll> compare(vector<ll> a, vector<ll> b){
            rep(i, a.size()){
                a[i] = max(a[i], b[i]);
            }
            return a;
        }
};

int main(int argc, const char * argv[]) {
    //提出時、消す----//
    //--------------//


    // input
    cout << fixed << setprecision(10);
    ll N; cin >> N;
    string S; cin >> S;
    ll Q; cin >> Q;
    LazySegmentTree seg;
    vector<vector<ll> > v(S.size());
    rep(i, S.size()){
        vector<ll> tmp(30);
        tmp[S[i] - 'a'] = 1;
        v[i] = tmp;
    }
    // print(v);
    seg.init(v);


    // variable
    ll ans = 0;
    // solve
    // 1 -> change
    // 2 -> out
    rep(i, Q){
        ll type; cin >> type;
        if(type == 1){
            // change
            ll l; cin >> l;
            char a; cin >> a;
            vector<ll> tmp(30);
            tmp[a - '0'] = 1;
            seg.update(l, l+1, tmp);
        }
        else{
            // out
            ll l, r; cin >> l >> r;
            l--; r--;
            vector<ll> res = seg.find(l, r+1);
            ll out = 0;
            rep(i, 30){
                if(res[i])out++; 
            }
            print(out);
        }
    }
    
    return 0;
}