unittest
{
	assert( [ "7", "abcdbbd", "6", "2 3 6", "1 5 z", "2 1 1", "1 4 a", "1 7 d", "2 1 7" ].parse.expand.solve == "3\n1\n5" );
}



import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = input.front.to!( long );
	input.popFront;
	auto s = input.front.to!( dchar[] );
	input.popFront;
	auto q = input.front.to!( long );
	auto qss = new dchar[][ 3 ][ q ];
	foreach( ref qs; qss )
	{
		input.popFront;
		qs = input.front.split.to!( dchar[][] );
	}
	return tuple( s, qss );
}

auto solve( dchar[] s, dchar[][ 3 ][] qss )
{
	BinaryIndexedTree[ 26 ] bits;
	foreach( ref bit; bits )
	{
		bit = BinaryIndexedTree( s.length );
	}
	foreach( i, c; s )
	{
		bits[ c - 'a' ].add( i, 1 );
	}
	
	long[] anss;
	foreach( qs; qss )
	{
		if( qs[ 0 ] == "1" )
		{
			auto i = qs[ 1 ].to!( long ) - 1;
			auto c = qs[ 2 ].front;
			if( s[ i ] != c )
			{
				bits[ s[ i ] - 'a' ].add( i, -1 );
				s[ i ] = c;
				bits[ s[ i ] - 'a' ].add( i, 1 );
			}
		}
		else
		{
			auto l = qs[ 1 ].to!( long ) - 1;
			auto r = qs[ 2 ].to!( long );
			auto t = 0L;
			foreach( i, bit; bits )
			{
				t += ( 0 < bit.sum( l, r ) );
			}
			anss ~= t;
		}
	}
	return anss.to!( string[] ).join( "\n" );
}

struct BinaryIndexedTree
{
	private long[] ps;
	
	public this( long n )
	{
		ps.length = 1 + n;
	}
	
	public void add( long i, long v )
	{
		for( auto j = i + 1; j < ps.length; j += j & -j ) ps[ j ] += v;
	}
	
	public auto sum( long l, long r )
	{
		auto lt = 0L;
		auto rt = 0L;
		for( auto j = l; 0 < j; j -= j & -j ) lt += ps[ j ];
		for( auto j = r; 0 < j; j -= j & -j ) rt += ps[ j ];
		return rt - lt;
	}
}
