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: Time Limit Exceeded)

namespace AtCoderCS
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Linq;
    using static System.Console;
    using static System.Math;
    using static Macro;

    class Program
    {
        void Solve()
        {
            var N = IN.Int;
            var S = IN.String.ToCharArray();
            var Q = IN.Int;
            REP(Q, i =>
            {
                var type = IN.Int;
                switch (type)
                {
                    case 1:
                        var iq = IN.Int - 1;
                        var cq = IN.Char;
                        S[iq] = cq;
                        break;
                    case 2:
                        var lq = IN.Int - 1;
                        var rq = IN.Int - 1;
                        WriteLine(
                            S.Skip(lq).Take(rq - lq + 1).Distinct().Count()
                        );
                        break;
                    default:
                        break;
                }
            });
        }

        private SimpleInput IN = new SimpleInput();
        private SimpleOutput OUT = new SimpleOutput();

        void Stream()
        {
            Solve();
            OUT.Flush();
        }

        static void Main(string[] args)
            => new Program().Stream();
    }

    #region IO
    class SimpleInput
    {
        private string[] _nextBuffer;
        private int _bufferCnt;
        private readonly char[] _cs = new char[] {' ', '"', ','};

        public SimpleInput()
        {
            _nextBuffer = new string[0];
            _bufferCnt = 0;
        }

        string Next()
        {
            if (_bufferCnt < _nextBuffer.Length) return _nextBuffer[_bufferCnt++];
            var st = ReadLine();
            while (st == string.Empty) st = ReadLine();
            if (st != null) _nextBuffer = st.Split(_cs, StringSplitOptions.RemoveEmptyEntries);
            _bufferCnt = 0;
            return _nextBuffer[_bufferCnt++];
        }

        public string String => Next();
        public char Char => char.Parse(String);
        public int Int => int.Parse(String);
        public long Long => long.Parse(String);
        public double Double => double.Parse(String);
    }

    class SimpleOutput
    {
        private readonly StreamWriter _sw = new StreamWriter(OpenStandardOutput())
        {
#if DEBUG
            AutoFlush = true
#else
            AutoFlush = false
#endif
        };

        public SimpleOutput()
        {
            SetOut(_sw);
        }

        public void Flush() => Out.Flush();
    }
    #endregion

    #region MACRO
    static class Macro
    {
        public static void FOR(int a, int b, int n, Action<int> f)
        {
            for (int i = a; i < b; i += n) f(i);
        }

        public static void FOR(int a, int b, Action<int> f) => FOR(a, b, 1, f);
        public static void REP(int a, Action<int> f) => FOR(0, a, f);
    }
    #endregion

    class UnionFind
    {
        private int[] data;

        public UnionFind(int n)
        {
            data = new int[n + 1];
            for (var i = 0; i < n + 1; ++i) data[i] = -1;
        }

        public void Unite(int x, int y)
        {
            x = Root(x);
            y = Root(y);
            if (x == y) return;
            if (data[y] < data[x]) Swap(ref x, ref y);
            data[x] += data[y];
            data[y] = x;
        }

        public bool Find(int x, int y) => Root(x) == Root(y);
        public int Root(int x) => data[x] < 0 ? x : Root(data[x]);
        public int Size(int x) => -data[Root(x)];

        private void Swap(ref int a, ref int b)
        {
            var tmp = b;
            b = a;
            a = tmp;
        }
    }
}