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 Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.util.*;
import java.util.function.BiFunction;
import java.io.*;


public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        int N = sc.nextInt();
        char[] S = sc.next().toCharArray();
        int q = sc.nextInt();
        Integer[][] alp = new Integer[26][N];
        for(int i=0;i<26;i++){
            Arrays.fill(alp[i], 0);
        }
        StringBuilder result = new StringBuilder();
        SegmentTree<Integer>[] t = new SegmentTree[26];
        for(int i=0;i<N;i++){
            alp[S[i]-'a'][i]++;
        }
        for(int i=0;i<26;i++){
            t[i] = new SegmentTree<>(alp[i], Integer::sum, 0);
        }
        for(int i=0;i<q;i++){
            if(sc.nextInt()==1){
                int iq = sc.nextInt();
                char cq = sc.next().charAt(0);
                if(S[iq-1]==cq) continue;
                if(t[S[iq-1]-'a'].query(0, iq)>0) t[S[iq-1]-'a'].update(iq, Integer::sum, -1);
                t[cq-'a'].update(iq, Integer::sum, 1);
                S[iq-1] = cq;
            }
            else{
                int res = 0;
                int l = sc.nextInt();
                int r = sc.nextInt();
                for(int j=0;j<26;j++){
                    if(t[j].query(l-1, r)>0){
                        res++;
                    }
                }
                result.append(res+"\n");
            }
        }

        out.println(result);
        out.flush();
    }

}

@SuppressWarnings("unchecked")
class SegmentTree<T> {
    private BiFunction<T, T, T> f;
    private int n;
    private T d1;
    private T[] dat;
    private  SegmentTree(T[] dat, int n_, BiFunction<T, T, T> f, T d1){
        this.f = f;
        this.d1 = d1;
        init(n_);
        build(dat);
    }

    public SegmentTree(T[] dat, BiFunction<T, T, T> f, T d1){
        this(dat, dat.length, f, d1);
    }

    public SegmentTree(int n_, BiFunction<T, T, T> f, T d1){
        this((T[]) new Object[0], n_, f, d1);
    }

    private void init(int n_){
        n = 1;
        while(n<n_) this.n *= 2;
        this.dat = (T[]) new Object[2 * this.n - 1];
    }

    private void build(T[] v){
        for(int i=0;i<n;i++) dat[i+n-1] = i < v.length ? v[i]: d1;
        for(int i=n-2;i>=0;i--) dat[i] = f.apply(dat[i*2+1], dat[i*2+2]);
    }

    public <E> void update(int k,BiFunction<T,E,T> g, E a){
        k += n-1;
        dat[k] = g.apply(dat[k], a);
        while(k>0){
            k = (k-1)/2;
            dat[k] = f.apply(dat[k*2+1], dat[k*2+2]);
        }
    }

    private T query(int a, int b, int k,int l, int r){
        if(r<=a || b<=l) return d1;
        if(a<=l&&r<=b) return dat[k];
        T vl = query(a, b, k*2+1, l, (l+r)/2);
        T vr = query(a, b, k*2+2, (l+r)/2, r);
        return f.apply(vl, vr);
    }

    public T query(int a, int b){
        return query(a, b, 0, 0, n);
    }
}