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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using static Assistant.Input;
using System.Linq;
using Assistant;
using System.Text;

namespace ABC157E
{
    class Program
    {
        static void Main(string[] args)
        {
            var N = ReadInt;
            var S = Console.ReadLine();
            var Q = ReadInt;

            BIT[] bits = new BIT[26].Select(a => new BIT(N + 1)).ToArray();
            for (int i = 0; i < N; i++)
            {
                int index = S[i] - 'a';
                bits[index].Add(i + 1, i + 1, 1);
            }
            //for (int i = 0; i < 26; i++)
            //{
            //    Console.Write(i + ":");
            //    bits[i].DrawBIT();
            //}

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < Q; i++)
            {
                var input = Console.ReadLine().Split();
                if (input[0][0] == '1')
                {
                    //change
                    int index = int.Parse(input[1]);
                    int to = input[2][0] - 'a';
                    for (int k = 0; k < 26; k++)
                    {
                        long a = bits[k].Sum(index, index);
                        if (to == k)
                        {
                            if (a != 0) continue;
                            bits[k].Add(index, index, 1);
                        }
                        else if (a > 0)
                        {
                            bits[k].Add(index, index, -1);
                        }
                    }
                }
                else
                {
                    //count
                    int l = int.Parse(input[1]);
                    int r = int.Parse(input[2]);
                    int count = 0;
                    for (int k = 0; k < 26; k++)
                    {
                        if (bits[k].Sum(l, r) > 0) count++;
                    }
                    sb.AppendLine(count.ToString());
                }
                //for (int t = 0; t < 26; t++)
                //{
                //    Console.Write(t + 1 + ":");
                //    bits[t].DrawBIT();
                //}

            }

            Console.Write(sb);
        }


    }

    class BIT
    {
        long[] bit0, bit1;  //1-indexed
        int n;
        public BIT(int n)
        {
            bit0 = new long[n + 1];
            bit1 = new long[n + 1];
            this.n = n;
        }

        public long Sum(int l, int r)
        {
            long ret = 0;
            ret += Sum(bit0, r) + Sum(bit1, r) * r;
            ret -= Sum(bit0, l - 1) + Sum(bit1, l - 1) * (l - 1);
            return ret;
        }

        long Sum(long[] bit, int i)
        {
            long s = 0;
            while (i > 0)
            {
                s += bit[i];
                i -= i & -i;
            }
            return s;
        }

        public void Add(int l, int r, int a)
        {
            Add(bit0, l, -a * (l - 1));
            Add(bit1, l, a);
            Add(bit0, r + 1, a * r);
            Add(bit1, r + 1, -a);
        }

        void Add(long[] bit, int i, int a)
        {
            while (i <= n)
            {
                bit[i] += a;
                i += i & -i;
            }
        }

        public void DrawBIT()
        {
            for (int i = 1; i <= n; i++)
            {
                Console.Write(Sum(i, i) + " ");
            }
            Console.WriteLine();
        }
    }
}

namespace Assistant
{
    static class Input
    {
        static List<string> line = new List<string>();
        static int index = 0;
        static String ReadNext()
        {
            if (line.Count <= index) line.AddRange(Console.ReadLine().Split());
            return line[index++];
        }
        public static string ReadString => ReadNext();
        public static int ReadInt => int.Parse(ReadNext());
        public static long ReadLong => long.Parse(ReadNext());
        public static int[] ReadInts => Console.ReadLine().Split().Select(int.Parse).ToArray();
        public static long[] NextLongs => Console.ReadLine().Split().Select(long.Parse).ToArray();
    }

    static class Debug
    {
        //drawmap
        //drawarray
    }
}