import core.bitop, std.algorithm, std.ascii, std.bigint, std.conv, std.math,
    std.functional, std.numeric, std.range, std.stdio, std.string, std.random,
    std.typecons, std.container, std.format;

// dfmt off
T lread(T = long)(){return readln.chomp.to!T();}
T[] aryread(T = long)(){return readln.split.to!(T[])();}
void scan(TList...)(ref TList Args){auto line = readln.split();
foreach (i, T; TList){T val = line[i].to!(T);Args[i] = val;}}
alias sread = () => readln.chomp();enum MOD = 10 ^^ 9 + 7;
alias PQueue(T, alias less = "a<b") = BinaryHeap!(Array!T, less);
// dfmt on

void main()
{
    long N = lread();
    char[] S = sread().dup;
    long Q = lread();
    auto bit = new BinaryIndexedTree[]('z' - 'a' + 1);
    foreach (i; 0 .. bit.length)
        bit[i] = BinaryIndexedTree(N);
    foreach (i; 0 .. N)
    {
        bit[S[i] - 'a'].add(i + 1, 1);
    }
    outer: foreach (_; 0 .. Q)
    {
        auto input = readln.split();
        long a = input[1].to!long();
        if (input[0] == "1")
        {
            char b = input[2][0];
            if (S[a - 1] == b)
                continue outer;
            bit[S[a - 1] - 'a'].add(a, -1);
            bit[b - 'a'].add(a, 1);
            S[a - 1] = cast(char) b;
        }
        if (input[0] == "2")
        {
            long b = input[2].to!long();
            long ans;
            foreach (c; 0 .. bit.length)
                ans += (bit[c].sum(b) - bit[c].sum(a - 1) != 0);
            writeln(ans);
        }
    }
}

/// BIT (1-indexed)
alias BinaryIndexedTree = BinaryIndexedTreeImpl!long;
struct BinaryIndexedTreeImpl(T)
{
    T[] _data;
    this(long n)
    {
        _data = new T[](n + 1);
    }

    T sum(long i)
    {
        T ans;
        for (; 0 < i; i -= (i & -i))
            ans += _data[i];
        return ans;
    }

    void add(long i, T x)
    {
        for (; i < _data.length; i += (i & -i))
            _data[i] += x;
    }
}
