using System;
using System.Collections.Generic;
using System.Windows;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Atcoder
{
    public class Program
    {
        static void Main(string[] args)
        {
            var n = Read().Int();
            var s = Read().ToCharArray();
            var q = Read().Int();

            var l = new List<Set<int>>();
            for (int i = 0; i < 26; i++)
            {
                l.Add(new Set<int>());
            }

            for (int i = 0; i < n; i++)
            {
                l[s[i] - 'a'].Insert(i);
            }

            var ansl = new List<int>();
            for (int i = 0; i < q; i++)
            {
                var r2 = ReadSplit();
                var type = r2[0].Int();
                if (type == 1)
                {
                    var iq = r2[1].Int() - 1;
                    var cq = r2[2].ToCharArray()[0];
                    l[s[iq] - 'a'].Remove(iq);
                    s[iq] = cq;
                    l[s[iq] - 'a'].Insert(iq);
                }
                else
                {
                    var lq = r2[1].Int() - 1;
                    var rq = r2[2].Int() - 1;
                    var ans = 0;
                    for (int j = 0; j < 26; j++)
                    {
                        var low = l[j].LowerBound(lq);
                        var up = l[j].UpperBound(rq);
                        if (low < up)
                        {
                            ans++;
                        }
                    }
                    ansl.Add(ans);
                }
            }
            for (int i = 0; i < ansl.Count; i++)
            {
                Write(ansl[i]);
            }
            Read();
        }

        public class SB_BinarySearchTree<T> where T : IComparable
        {
            public class Node
            {
                public T Value;
                public Node LChild;
                public Node RChild;
                public int Count;     //size of the sub tree

                public Node(T v)
                {
                    Value = v;
                    Count = 1;
                }
            }

            static Random _rnd = new Random();

            public static int Count(Node t)
            {
                return t == null ? 0 : t.Count;
            }

            static Node Update(Node t)
            {
                t.Count = Count(t.LChild) + Count(t.RChild) + 1;
                return t;
            }

            public static Node Merge(Node l, Node r)
            {
                if (l == null || r == null) return l == null ? r : l;

                if ((double)Count(l) / (double)(Count(l) + Count(r)) > _rnd.NextDouble())
                {
                    l.RChild = Merge(l.RChild, r);
                    return Update(l);
                }
                else
                {
                    r.LChild = Merge(l, r.LChild);
                    return Update(r);
                }
            }

            /// <summary>
            /// split as [0, k), [k, n)
            /// </summary>
            public static Tuple<Node, Node> Split(Node t, int k)
            {
                if (t == null) return new Tuple<Node, Node>(null, null);
                if (k <= Count(t.LChild))
                {
                    var s = Split(t.LChild, k);
                    t.LChild = s.Item2;
                    return new Tuple<Node, Node>(s.Item1, Update(t));
                }
                else
                {
                    var s = Split(t.RChild, k - Count(t.LChild) - 1);
                    t.RChild = s.Item1;
                    return new Tuple<Node, Node>(Update(t), s.Item2);
                }
            }

            public static Node Remove(Node t, T v)
            {
                if (Find(t, v) == null) return t;
                return RemoveAt(t, LowerBound(t, v));
            }

            public static Node RemoveAt(Node t, int k)
            {
                var s = Split(t, k);
                var s2 = Split(s.Item2, 1);
                return Merge(s.Item1, s2.Item2);
            }

            public static bool Contains(Node t, T v)
            {
                return Find(t, v) != null;
            }

            public static Node Find(Node t, T v)
            {
                while (t != null)
                {
                    var cmp = t.Value.CompareTo(v);
                    if (cmp > 0) t = t.LChild;
                    else if (cmp < 0) t = t.RChild;
                    else break;
                }
                return t;
            }

            public static Node FindByIndex(Node t, int idx)
            {
                if (t == null) return null;

                var currentIdx = Count(t) - Count(t.RChild) - 1;
                while (t != null)
                {
                    if (currentIdx == idx) return t;
                    if (currentIdx > idx)
                    {
                        t = t.LChild;
                        currentIdx -= (Count(t == null ? null : t.RChild) + 1);
                    }
                    else
                    {
                        t = t.RChild;
                        currentIdx += (Count(t == null ? null : t.LChild) + 1);
                    }
                }

                return null;
            }

            public static int UpperBound(Node t, T v)
            {
                var torg = t;
                if (t == null) return -1;

                var ret = Int32.MaxValue;
                var idx = Count(t) - Count(t.RChild) - 1;
                while (t != null)
                {
                    var cmp = t.Value.CompareTo(v);

                    if (cmp > 0)
                    {
                        ret = Math.Min(ret, idx);
                        t = t.LChild;
                        idx -= (Count(t == null ? null : t.RChild) + 1);
                    }
                    else if (cmp <= 0)
                    {
                        t = t.RChild;
                        idx += (Count(t == null ? null : t.LChild) + 1);
                    }
                }
                return ret == Int32.MaxValue ? Count(torg) : ret;
            }

            public static int LowerBound(Node t, T v)
            {
                var torg = t;
                if (t == null) return -1;

                var idx = Count(t) - Count(t.RChild) - 1;
                var ret = Int32.MaxValue;
                while (t != null)
                {
                    var cmp = t.Value.CompareTo(v);
                    if (cmp >= 0)
                    {
                        if (cmp == 0) ret = Math.Min(ret, idx);
                        t = t.LChild;
                        if (t == null) ret = Math.Min(ret, idx);
                        idx -= t == null ? 0 : (Count(t.RChild) + 1);
                    }
                    else if (cmp < 0)
                    {
                        t = t.RChild;
                        idx += (Count(t == null ? null : t.LChild) + 1);
                        if (t == null) return idx;
                    }
                }
                return ret == Int32.MaxValue ? Count(torg) : ret;
            }

            public static Node Insert(Node t, T v)
            {
                var ub = LowerBound(t, v);
                return InsertByIdx(t, ub, v);
            }

            static Node InsertByIdx(Node t, int k, T v)
            {
                var s = Split(t, k);
                return Merge(Merge(s.Item1, new Node(v)), s.Item2);
            }

            public static IEnumerable<T> Enumerate(Node t)
            {
                var ret = new List<T>();
                Enumerate(t, ret);
                return ret;
            }

            static void Enumerate(Node t, List<T> ret)
            {
                if (t == null) return;
                Enumerate(t.LChild, ret);
                ret.Add(t.Value);
                Enumerate(t.RChild, ret);
            }
        }

        /// <summary>
        /// C-like set
        /// </summary>
        public class Set<T> where T : IComparable
        {
            protected SB_BinarySearchTree<T>.Node _root;

            public T this[int idx] { get { return ElementAt(idx); } }

            public int Count()
            {
                return SB_BinarySearchTree<T>.Count(_root);
            }

            public virtual void Insert(T v)
            {
                if (_root == null) _root = new SB_BinarySearchTree<T>.Node(v);
                else
                {
                    if (SB_BinarySearchTree<T>.Find(_root, v) != null) return;
                    _root = SB_BinarySearchTree<T>.Insert(_root, v);
                }
            }

            public void Clear()
            {
                _root = null;
            }

            public void Remove(T v)
            {
                _root = SB_BinarySearchTree<T>.Remove(_root, v);
            }

            public bool Contains(T v)
            {
                return SB_BinarySearchTree<T>.Contains(_root, v);
            }

            public T ElementAt(int k)
            {
                var node = SB_BinarySearchTree<T>.FindByIndex(_root, k);
                if (node == null) throw new IndexOutOfRangeException();
                return node.Value;
            }

            public int Count(T v)
            {
                return SB_BinarySearchTree<T>.UpperBound(_root, v) - SB_BinarySearchTree<T>.LowerBound(_root, v);
            }

            public int LowerBound(T v)
            {
                return SB_BinarySearchTree<T>.LowerBound(_root, v);
            }

            public int UpperBound(T v)
            {
                return SB_BinarySearchTree<T>.UpperBound(_root, v);
            }

            public Tuple<int, int> EqualRange(T v)
            {
                if (!Contains(v)) return new Tuple<int, int>(-1, -1);
                return new Tuple<int, int>(SB_BinarySearchTree<T>.LowerBound(_root, v), SB_BinarySearchTree<T>.UpperBound(_root, v) - 1);
            }

            public List<T> ToList()
            {
                return new List<T>(SB_BinarySearchTree<T>.Enumerate(_root));
            }
        }

        public static string Read()
        {
            return Console.ReadLine();
        }

        public static string[] ReadSplit()
        {
            return Console.ReadLine().Split(' ');
        }

        public static void WriteRead(object str)
        {
            Console.WriteLine(str);
            Read();
        }

        public static void Write(object str)
        {
            Console.WriteLine(str);
        }

        private static bool ChangeMin<T>(ref T a, T b) where T : IComparable
        {
            if (a.CompareTo(b) > 0)
            {
                a = b;
                return true;
            }
            return false;
        }

        private static bool ChangekMax<T>(ref T a, T b) where T : IComparable
        {
            if (b.CompareTo(a) > 0)
            {
                a = b;
                return true;
            }
            return false;
        }
    }
}


public static class Extentions
{
    public static int Int(this object obj)
    {
        return int.Parse(obj.ToString());
    }

    public static long Long(this object obj)
    {
        return long.Parse(obj.ToString());
    }

    public static decimal Decimal(this object obj)
    {
        return decimal.Parse(obj.ToString());
    }

    public static double Double(this object obj)
    {
        return double.Parse(obj.ToString());
    }

    public static T2 GetValueZero<T1, T2>(this Dictionary<T1, T2> d, T1 key) where T2 : struct
    {
        T2 value;
        if (d.TryGetValue(key, out value))
        {
            return value;
        }
        return new T2();
    }
}



Measured memory_bytes: 40624