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 (Python):


import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

class BIT:
    """ Binary Indexed Tree """

    def __init__(self, n):
        
        n += 1
        nv = 1
        while nv < n:
            nv *= 2
        self.size = nv
        self.tree = [0] * nv

    def sum(self, i):
        """ [0, i]を合計する """
        s = 0
        i += 1
        while i > 0:
            s += self.tree[i-1]
            i -= i & -i
        return s

    def add(self, i, x):
        """ 値の追加：添字i, 値x """
        i += 1
        while i <= self.size:
            self.tree[i-1] += x
            i += i & -i

    def get(self, l, r=None):
        """ 区間和の取得 [l, r) """
        
        if r is None: r = l + 1
        res = 0
        if r: res += self.sum(r-1)
        if l: res -= self.sum(l-1)
        return res

    def update(self, i, x):
        """ 値の更新：添字i, 値x """
        self.add(i, x - self.get(i))

N = INT()
S = [ord(c)-97 for c in input()]
BITs = [BIT(N+1) for i in range(26)]
for i, s in enumerate(S):
    BITs[s].add(i, 1)

Q = INT()
for _ in range(Q):
    q = list(input().split())
    if q[0] == '1':
        _, i, c = q
        i = int(i) - 1
        c = ord(c) - 97
        if S[i] != c:
            prev = S[i]
            S[i] = c
            BITs[prev].add(i, -1)
            BITs[c].add(i, 1)
    else:
        _, l, r = q
        l, r = int(l) - 1, int(r) - 1
        ans = 0
        for c in range(26):
            if BITs[c].get(l, r+1) > 0:
                ans += 1
        print(ans)

Solution (Python):

class BinaryIndexedTree:
    def __init__(self, size):
        size = 1 << (size-1).bit_length()
        self.data = [0] * (size+1)
        self.size = size
    
    def add(self, i, w):
        i += 1
        while i <= self.size:
            self.data[i] += w
            i += i & -i

    def sum(self, i):
        """
        [0,i)
        """
        result = 0
        while i > 0:
            result += self.data[i]
            i -= i & -i
        return result

    __getitem__ = sum

    def lower_bound(self, v):
        """
        return smallest i such that v < sum(data[:i])
        """

        s,pos = 0,0
        N = self.size
        k = N
        while k > 0:
            i = pos+k
            if i <= N:
                x = s+self.data[i]
                if x < v:
                    s = x
                    pos = i
            k >>= 1
        return pos

N = int(input())
S = input()
S = list(ord(c)-ord('a') for c in S)
bits = tuple(BinaryIndexedTree(N) for _ in range(26))

for i,c in enumerate(S):
    bit = bits[c]
    bit.add(i, 1)


def q1(i, c):
    i = int(i)-1
    bit = bits[S[i]]
    bit.add(i,-1)
    c = ord(c)-ord('a')
    bit = bits[c]
    bit.add(i,1)
    S[i] = c
def q2(l,r):
    l,r = int(l)-1,int(r)
    print(sum(bit.sum(r) > bit.sum(l) for bit in bits))


Q = int(input())
for _ in range(Q):
    q,x,y = input().split()

    if q == '1':
        q1(x,y)
    else:
        q2(x,y)

Solution (Python):
import sys
input = sys.stdin.readline

N=int(input())
S=list(input().strip())
Q=int(input())

LEN=N

BIT=[[0]*(LEN+1) for i in range(26)]

def update(v,w,i): 
    while v<=LEN:
        BIT[i][v]+=w
        v+=(v&(-v)) 

def getvalue(v,i): 
    ANS=0
    while v!=0:
        ANS+=BIT[i][v]
        v-=(v&(-v)) 
    return ANS

for i in range(N):
    update(i+1,1,ord(S[i])-97)

for i in range(Q):
    qf,x,y=input().split()
    qf=int(qf)

    if int(qf)==1:
        x=int(x)
        update(x,-1,ord(S[x-1])-97)
        update(x,1,ord(y)-97)
        S[x-1]=y

    else:
        x=int(x)
        y=int(y)
        ANS=0
        for i in range(26):
            if getvalue(y,i)-getvalue(x-1,i)>0:
                ANS+=1

        print(ANS)

Solution (Python):
def main():
    import sys
    input = sys.stdin.readline

    class Bit:
        def __init__(self, n):
            self.size = n
            self.tree = [0] * (n + 1)

        def sum(self, i):
            s = 0
            while i > 0:
                s += self.tree[i]
                i -= i & -i
            return s

        def add(self, i, x):
            while i <= self.size:
                self.tree[i] += x
                i += i & -i

    N = int(input())
    S = input().rstrip('\n')
    Q = int(input())

    S = [s for s in S]

    bit = [Bit(N) for _ in range(26)]
    for i, s in enumerate(S):
        j = ord(s) - 97
        bit[j].add(i+1, 1)
    for _ in range(Q):
        flg, l, r = input().split()
        if flg == '1':
            i = int(l)
            c = r
            si = S[i-1]
            bit[ord(si)-97].add(i, -1)
            bit[ord(c)-97].add(i, 1)
            S[i-1] = c
        else:
            l = int(l)
            r = int(r)
            ans = 0
            for j in range(26):
                if bit[j].sum(r) - bit[j].sum(l-1):
                    ans += 1
            print(ans)


if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.readline
n = int(input())

ss = list(input())
s = []
for i in range(n):
    s.append(1<<(ord(ss[i])-97))


def segfunc(x,y):
    return x | y

def init(init_val):
    
    for i in range(n):
        seg[i+num-1]=init_val[i]    
    
    for i in range(num-2,-1,-1) :
        seg[i]=segfunc(seg[2*i+1],seg[2*i+2]) 
    
def update(k,x):
    k += num-1
    seg[k] = x
    while k:
        k = (k-1)//2
        seg[k] = segfunc(seg[k*2+1],seg[k*2+2])
    
def query(p,q):
    if q<=p:
        return ide_ele
    p += num-1
    q += num-2
    res=ide_ele
    while q-p>1:
        if p&1 == 0:
            res = segfunc(res,seg[p])
        if q&1 == 1:
            res = segfunc(res,seg[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = segfunc(res,seg[p])
    else:
        res = segfunc(segfunc(res,seg[p]),seg[q])
    return res


ide_ele = 0


num =2**(n-1).bit_length()
seg=[ide_ele]*2*num

init(s)


def popcnt(n):
    c = (n & 0x5555555555555555) + ((n>>1) & 0x5555555555555555)
    c = (c & 0x3333333333333333) + ((c>>2) & 0x3333333333333333)
    c = (c & 0x0f0f0f0f0f0f0f0f) + ((c>>4) & 0x0f0f0f0f0f0f0f0f)
    c = (c & 0x00ff00ff00ff00ff) + ((c>>8) & 0x00ff00ff00ff00ff)
    c = (c & 0x0000ffff0000ffff) + ((c>>16) & 0x0000ffff0000ffff)
    c = (c & 0x00000000ffffffff) + ((c>>32) & 0x00000000ffffffff)
    return c

q = int(input())

for i in range(q):
    qq,xx,yy = map(str,input().split())
    if qq == '1':
        xx = int(xx)
        update(xx-1,1<<(ord(yy)-97))
    else:
        xx,yy = int(xx),int(yy)
        res = query(xx-1,yy)
        print(popcnt(res))

Solution (Python):
N = int(input())
def idx(s):
    return ord(s)-97

class BIT:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        i += 1
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        i += 1
        while i <= self.size:
            self.tree[i] += x
            i += i & -i

d = {}
for i in range(26):
    d[i] = BIT(N)

S = input()
for i in range(N):
    d[idx(S[i])].add(i,1)
S = list(S)
Q = int(input())
for _ in range(Q):
    q = input().split()
    if q[0]=='1':
        i = int(q[1])-1
        s = S[i]
        d[idx(s)].add(i,-1)
        S[i] = q[2]
        d[idx(q[2])].add(i,1)
    else:
        l,r = int(q[1])-1,int(q[2])-1
        res = 0
        for i in range(26):
            c = d[i].sum(r)
            if l!=0:
                c -= d[i].sum(l-1)
            c = min(1,c)
            res += c
        print(res)

Solution (Python):

def bitadd(a,w,bit): 
 
    x = a
    while x <= (len(bit)-1):
        bit[x] += w
        x += x & (-1 * x)
 
def bitsum(a,bit): 

    if a == 0:
        return 0
 
    ret = 0
    x = a
    while x > 0:
        ret += bit[x]
        x -= x & (-1 * x)
    return ret


alp = "abcdefghijklmnopqrstuvwxyz"

al = {}

for i in range(26):
    al[alp[i]] = i

N = int(input())

BITS = [ [0] * (N+1) for i in range(26) ]

S = list(input())

for i in range(N):

    bitadd(i+1,1,BITS[al[S[i]]])

Q = int(input())
for i in range(Q):

    qs,x,y = input().split()
    qs = int(qs)
    
    if qs == 1:
        x = int(x)
        bitadd(x,-1,BITS[al[S[x-1]]])
        bitadd(x,1,BITS[al[y]])
        S[x-1] = y

    else:
        x = int(x)
        y = int(y)

        ans = 0
        for j in range(26):
            ans += min(1 , bitsum(y,BITS[j]) - bitsum(x-1,BITS[j]))

        print (ans)

Solution (Python):
class BIT: 
    def __init__(self, n):
        self.size = n
        self.tree = [0]*(n+1)
        self.depth = n.bit_length()
        self.n0 = 1<<self.depth

    def get_sum(self, i): 
        s = 0; i += 1
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s
    def query(self,l,r): 
        return self.get_sum(r) - self.get_sum(l-1) 
    def add(self, i, x):
        i += 1
        while i <= self.size:
            self.tree[i] += x
            i += i & -i
        
    
    def bisect_left(self,w):
        
        
        if w <= 0: return 0
        x,k = 0,self.n0
        for _ in range(self.depth):
            k >>= 1
            if x+k <= self.size and self.tree[x+k] < w:
                w -= self.tree[x+k]
                x += k
        return x





import sys
readline = sys.stdin.readline
read = sys.stdin.read






n,s,q,*query = read().split()
n = int(n)
q = int(q)

B = [BIT(n) for _ in range(26)]

SS = list(map(lambda x: ord(x)-97,s))
for i,c in enumerate(SS):
    B[c].add(i,1)

for I in range(q):
    l,r,c = query[3*I:3*(I+1)]
    l = int(l)
    r = int(r)-1
    
    if l == 1:
        z = ord(c)-97
        B[SS[r]].add(r,-1)
        B[z].add(r,1)
        SS[r] = z
    else:
        c = int(c)-1
        res = 0
        for i in range(26):
            if B[i].query(r,c):
                res += 1
        print(res)

Solution (Python):
class SegmentTree:
	def __init__(self, orig, func, unit):
		_len = len(orig)
		self.func = func
		self.size = 1 << (_len - 1).bit_length()
		self.tree = [unit] * self.size + orig + [unit] * (self.size - _len)
		self.unit = unit

		for i in range(self.size - 1, 0, -1):
			self.tree[i] = func(self.tree[i * 2], self.tree[i * 2 + 1])

	def update(self, i, v):
		i += self.size
		self.tree[i] = v
		while i:
			i //= 2
			self.tree[i] = self.func(self.tree[i * 2], self.tree[i * 2 + 1])

	def find(self, l, r):
		l += self.size
		r += self.size
		ret = self.unit
		while l < r:
			if l & 1:
				ret = self.func(ret, self.tree[l])
				l += 1
			if r & 1:
				r -= 1
				ret = self.func(ret, self.tree[r])
			l //= 2
			r //= 2
		return ret

import sys
input=sys.stdin.readline
from operator import or_

n=int(input())
s=input()
li=[1<<ord(x)-97 for x in s[:-1]]
seg=SegmentTree(li,or_,0)
ans=[]
for _ in range(int(input())):
	f,x,y=input().split()
	if f=="1":
		x=int(x)
		seg.update(x-1,1<<ord(y)-97)
	else:
		x=int(x)
		y=int(y)
		z=seg.find(x-1,y)
		cnt=0
		for i in range(26):
			if z & (1<<i):
				cnt+=1
		ans.append(cnt)
print(*ans)

Solution (Python):

from collections import defaultdict,deque
from heapq import heappush, heappop
from itertools import permutations
import sys
import math
import bisect
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007
import operator
class SegmentTree:
    def __init__(self, size, default, op = operator.add):
        self.size = 2**size.bit_length()
        self.dat = [default]*(self.size*2)
        self.op = op

    def update(self, i, x):
        i += self.size
        self.dat[i] = x
        while i > 0:
            i >>= 1
            self.dat[i] = self.op(self.dat[i*2], self.dat[i*2+1])

    def add(self, i, x):
        i += self.size
        self.dat[i] = self.op(self.dat[i], x)
        while i > 0:
            i >>= 1
            self.dat[i] = self.op(self.dat[i], x)

    def get(self, a, b = None):
        if b is None:
            b = a + 1
        l, r = a + self.size, b + self.size
        res = None
        while l < r:
            if l & 1:
                if res is None:
                    res = self.dat[l]
                else:
                    res = self.op(res, self.dat[l])
                l += 1

            if r & 1:
                r -= 1
                if res is None:
                    res = self.dat[r]
                else:
                    res = self.op(res, self.dat[r])
            l >>= 1
            r >>= 1
        return res
def solve():
    n = I()
    S = list(input())
    m = ord("z")-ord("a")+1
    s = [SegmentTree(n,0) for i in range(m)]
    for i in range(n):
        k = ord(S[i])-ord("a")
        s[k].update(i,1)
    Q = I()
    for _ in range(Q):
        q = input().split()
        if q[0] == "1":
            i = int(q[1])-1
            if S[i] == q[2]:
                continue
            k = ord(S[i])-ord("a")
            s[k].update(i,0)
            k = ord(q[2])-ord("a")
            s[k].update(i,1)
            S[i] = q[2]
        else:
            l,r = q[1:]
            l = int(l)
            r = int(r)
            ans = 0
            for k in range(m):
                if s[k].get(l-1,r):
                    ans += 1
            print(ans)
    return


if __name__ == "__main__":
    solve()

Solution (Python):

class sumBIT():
    def __init__(self, N):
        self.N = N
        self.bit = [0 for _ in range(self.N+1)]
    
    def __str__(self):
        ret = []
        for i in range(1, self.N+1):
            ret.append(self.__getitem__(i))
        return "[" + ", ".join([str(a) for a in ret]) + "]"

    def __getitem__(self, i):
        s = 0
        while i > 0:
            s += self.bit[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.N:
            self.bit[i] += x
            i += i & -i

import sys
input = sys.stdin.readline

N = int(input())
S = list(input().rstrip())
Q = int(input())
Query = [list(map(str, input().split())) for _ in range(Q)]

Alp = [chr(i) for i in range(97, 97+26)]
BITs = {}
for i, a in enumerate(Alp):
    bit = sumBIT(N+3)
    BITs[a] = bit

for i, s in enumerate(S):
    BITs[s].add(i+2, 1)

for WWW, x, y in Query:
    if WWW == "1":
        i = int(x)
        for alp in Alp:
            if BITs[alp][i+1] - BITs[alp][i] > 0:
                BITs[alp].add(i+1, -1)
                break
        BITs[y].add(i+1, 1)
    else:
        l = int(x)
        r = int(y)
        ans = 0
        for alp in Alp:
            if BITs[alp][r+1] - BITs[alp][l] > 0:
                ans += 1
        print(ans)

Solution (Python):
import sys
range = xrange
input = raw_input

class segtree:
    def __init__(self, n):
        m = 1
        while m < n:
            m *= 2
        self.m = m
        self.data = [0]*(m + m)
    def add(self, i, x):
        i += self.m
        while i:
            self.data[i] += x
            i >>= 1

    def summer(self, l ,r):
        l += self.m
        r += self.m
        while l < r:
            if l & 1:
                if self.data[l]:
                    return True
                l += 1
            if r & 1:
                r -= 1
                if self.data[r]:
                    return True
            l >>= 1
            r >>= 1
        return False

orda = ord('a')

inp = sys.stdin.read().split(); ii = 0

n = int(inp[ii]); ii += 1
S = [ord(c) - orda for c in inp[ii]]; ii += 1

segs = [segtree(n) for _ in range(26)]
for i in range(n):
    segs[S[i]].add(i, 1)

q = int(inp[ii]); ii += 1
out = []
for _ in range(q):
    case = int(inp[ii]); ii += 1

    if case == 1:
        i = int(inp[ii]) - 1; ii += 1
        c = ord(inp[ii]) - orda; ii += 1

        segs[S[i]].add(i, -1)
        S[i] = c
        segs[S[i]].add(i, 1)
    else:
        l = int(inp[ii]) - 1; ii += 1
        r = int(inp[ii]); ii += 1
        out.append(sum(seg.summer(l,r) for seg in segs))
print '\n'.join(str(x) for x in out)

Solution (Python):
import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__

class Binary_Indexed_Tree():
    def __init__(self, n):
        self.n = n
        self.data = [0]*(n+1)

    def add(self, i, x):
        i += 1
        while i <= self.n:
            self.data[i] += x
            i += i & -i

    def get(self, i):
        i += 1
        return self.sum_range(i, i)

    def sum(self, i):
        i += 1
        ret = 0
        while i:
            ret += self.data[i]
            i &= i-1
        return ret

    def sum_range(self, l, r):
        return self.sum(r)-self.sum(l-1)

n = int(input())
s = input()
m = 26
orda = ord("a")
segs = [Binary_Indexed_Tree(n) for i in range(m)]
s = list(map(lambda x: ord(x)-orda, list(s)))
for i, c in enumerate(s):
    segs[c].add(i,1)

q = int(input())
for _ in range(q):
    f,i,c = input().split()
    f = int(f)
    if f == 1:
        i = int(i)-1
        c = ord(c)-orda
        if s[i] != c:
            segs[s[i]].add(i, -1)
            s[i] = c
            segs[s[i]].add(i, 1)
    else:
        l = int(i)-1
        r = int(c)-1
        ans = 0
        for x in range(m):
            if segs[x].sum_range(l,r) > 0:
                ans += 1
        print(ans)

Solution (Python):
def update(BIT,index,letter,value):
    while index < len(BIT):
        BIT[index][letter] += value
        index += index&-index

def sumQuery(BIT,index):
    letters = [0]*26
    while index > 0:
        for i in range(26):
            letters[i] += BIT[index][i]

        index -= index&-index

    return letters

def rangeQuery(BIT,l,r,ans):
    right = sumQuery(BIT,r)
    left = sumQuery(BIT,l-1)
    count = 0
    for i in range(26):
        right[i] -= left[i]
        if right[i] > 0:
            count += 1

    ans.append(count)

def main():
    n = int(input())
    s = list(input())
    q = int(input())
    BIT = [[0 for i in range(26)] for j in range(n+1)]
    ans = []

    for i in range(n):
        update(BIT,i+1,ord(s[i])-ord('a'),1)

    for i in range(q):
        query,index,c = map(str,input().split())
        query = int(query)
        if query == 1:
            index = int(index)
            update(BIT,index,ord(s[index-1])-ord('a'),-1)
            s[index-1] = c
            update(BIT,index,ord(s[index-1])-ord('a'),1)
        else:
            l,r = int(index),int(c)
            rangeQuery(BIT,l,r,ans)

    for i in ans:
        print(i)


main()

Solution (Python):
class SegmentTree():
    """一点更新、区間取得クエリをそれぞれO(logN)で答えるデータ構造を構築する
    update: i番目をvalに変更する
    get_min: 区間[begin, end)の最小値を求める
    """
    def __init__(self, n):
        self.n = n
        self.INF = 0
        self.size = 1
        while self.size < n:
            self.size *= 2
        self.node = [self.INF] * (2*self.size - 1)

    def update(self, i, val):
        i += (self.size - 1)
        self.node[i] = val
        while i > 0:
            i = (i - 1) // 2
            self.node[i] = self.node[2*i + 1] | self.node[2*i + 2]

    def get_min(self, begin, end):
        begin += (self.size - 1)
        end += (self.size - 1)
        s = 0
        while begin < end:
            if (end - 1) & 1:
                end -= 1
                s = s | self.node[end]
            if (begin - 1) & 1:
                s = s | self.node[begin]
                begin += 1
            begin = (begin - 1) // 2
            end = (end - 1) // 2
        return s

import sys
input = sys.stdin.readline


n = int(input())
s = input()
q = int(input())
query = [list(input().split()) for i in range(q)] 

alph = "abcdefghijklmnopqrstuvwxyz"
to_int = {char: i for i, char in enumerate(alph)}
st = SegmentTree(n)

for i, char in enumerate(s[0:n]):
    st.update(i, 1 << to_int[char]) 

for num, l, r in query:
    if num == "1":
        st.update(int(l) - 1, 1 << to_int[r]) 
    else:
        tmp = st.get_min(int(l) - 1, int(r))
        print(bin(tmp).count("1"))

Solution (Python):
import os
import sys

if os.getenv("LOCAL"):
    sys.stdin = open("_in.txt", "r")

sys.setrecursionlimit(10 ** 9)
INF = float("inf")
IINF = 10 ** 18
MOD = 10 ** 9 + 7




class BinaryIndexedTree:
    
    def __init__(self, size):
        """
        :param int size:
        """
        self._bit = [0] * size
        self._size = size

    def add(self, i, w):
        """
        i 番目に w を加える
        :param int i:
        :param int w:
        """
        x = i + 1
        while x <= self._size:
            self._bit[x - 1] += w
            x += x & -x

    def sum(self, i):
        """
        [0, i) の合計
        :param int i:
        """
        ret = 0
        while i > 0:
            ret += self._bit[i - 1]
            i -= i & -i
        return ret

    def __len__(self):
        return self._size


N = int(sys.stdin.buffer.readline())
S = list(sys.stdin.buffer.readline().decode().rstrip())
Q = int(sys.stdin.buffer.readline())
queries = [sys.stdin.buffer.readline().decode().rstrip().split() for _ in range(Q)]

bits = [BinaryIndexedTree(size=N) for _ in range(26)]
for i, c in enumerate(S):
    bits[ord(c) - ord('a')].add(i, 1)

ans = []
for q, a, b in queries:
    if q == '1':
        i = int(a) - 1
        c = str(b)
        bits[ord(S[i]) - ord('a')].add(i, -1)
        S[i] = c
        bits[ord(S[i]) - ord('a')].add(i, 1)
    if q == '2':
        l = int(a) - 1
        r = int(b) - 1
        cnt = 0
        for bit in bits:
            if bit.sum(r + 1) - bit.sum(l) > 0:
                cnt += 1
        ans.append(cnt)

print(*ans, sep='\n')

Solution (Python):
from collections import defaultdict,deque
import sys,heapq,bisect,math,itertools,string,queue,copy,time
sys.setrecursionlimit(10**8)
INF = float('inf')
mod = 10**9+7
eps = 10**-7
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpl_str(): return list(sys.stdin.readline().split())

class Node:
    def __init__(self,value,index=0):
        self.value = value
        self.index = index

    def __str__(self):
        return 'val : ' + str(self.value) + ' index : ' + str(self.index)


class SegmentTree:
    def __init__(self,N,default_list,default_value=INF):
        self.N0 = pow(2,(N-1).bit_length())
        self.nodes = [Node(default_value,i+1-self.N0) for i in range(2*self.N0-1)]
        for i in reversed(range(2*self.N0-1)):
            ind = i+1-self.N0
            if ind >= N:
                self.nodes[i].value = default_value
            elif N > ind >= 0:
                self.nodes[i].value = default_list[ind]
            else:
                self.nodes[i] = self.process(self.nodes[i*2+1],self.nodes[i*2+2])

    def __getitem__(self,key): 
        return self.nodes[key+self.N0-1].value

    def __setitem__(self,i,x): 
        i += self.N0 - 1
        self.nodes[i].value = x
        while i > 0:
            i = (i-1)//2
            self.nodes[i] = self.process(self.nodes[i*2+1],self.nodes[i*2+2])

    def __str__(self):
        return '['+', '.join(map(str,[self.nodes[i+self.N0-1].value for i in range(self.N0)]))+']'

    def query(self,L,R): 
        retnode = Node(0,0)
        L += self.N0
        R += self.N0
        while L < R:
            if R&1 :
                R -= 1
                retnode = self.process(retnode,self.nodes[R-1])
            if L&1 :
                retnode = self.process(retnode,self.nodes[L-1])
                L += 1
            L >>= 1; R >>= 1
        return retnode

    def process(self,node_x,node_y): 
        return Node(node_x.value|node_y.value)

N = inp()
S = list(input())

a = ord("a")
slist = []
for s in S:
    slist.append(1<<(ord(s)-a))


ST = SegmentTree(N, default_list=slist, default_value=0)

Q = inp()
ans = []
for _ in range(Q):
    a,b,c = input().split()
    if a == "2":
        ret = ST.query(int(b)-1,int(c))
        ans.append(str(bin(ret.value)).count("1"))
    else:
        tmp = 1<<(ord(c)-ord("a"))
        ST[int(b)-1] = tmp


print("\n".join(map(str,ans)))

Solution (Python):
import sys
readline = sys.stdin.readline
from operator import or_
class Segtree:
    def __init__(self, A, intv, initialize = True, segf = max):
        self.N = len(A)
        self.N0 = 2**(self.N-1).bit_length()
        self.intv = intv
        self.segf = segf
        if initialize:
            self.data = [intv]*self.N0 + A + [intv]*(self.N0 - self.N)
            for i in range(self.N0-1, 0, -1):
                self.data[i] = self.segf(self.data[2*i], self.data[2*i+1]) 
        else:
            self.data = [intv]*(2*self.N0)
        
    def update(self, k, x):
        k += self.N0
        self.data[k] = x
        while k > 0 :
            k = k >> 1
            self.data[k] = self.segf(self.data[2*k], self.data[2*k+1])
    
    def query(self, l, r):
        L, R = l+self.N0, r+self.N0
        s = self.intv
        while L < R:
            if R & 1:
                R -= 1
                s = self.segf(s, self.data[R])
            if L & 1:
                s = self.segf(s, self.data[L])
                L += 1
            L >>= 1
            R >>= 1
        return s
    
    def binsearch(self, l, r, check, reverse = False):
        L, R = l+self.N0, r+self.N0
        SL, SR = [], []
        while L < R:
            if R & 1:
                R -= 1
                SR.append(R)
            if L & 1:
                SL.append(L)
                L += 1
            L >>= 1
            R >>= 1
        
        if reverse:
            for idx in (SR + SL[::-1]):
                if check(self.data[idx]):
                    break
            else:
                return -1
            while idx < self.N0:
                if check(self.data[2*idx+1]):
                    idx = 2*idx + 1
                else:
                    idx = 2*idx
            return idx - self.N0
        else:
            for idx in (SL + SR[::-1]):
                if check(self.data[idx]):
                    break
            else:
                return -1
            while idx < self.N0:
                if check(self.data[2*idx]):
                    idx = 2*idx
                else:
                    idx = 2*idx + 1
            return idx - self.N0
def popcount(i):
    assert 0 <= i < 0x100000000
    i = i - ((i >> 1) & 0x55555555)
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
    return (((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) & 0xffffffff) >> 24


N = int(readline())
S = []
for s in readline().strip():
    S.append(1<<(ord(s) - 97))
Q = int(readline())
T = Segtree(S, 0, initialize = True, segf = or_)
Ans = []
for _ in range(Q):
    ty, x, y = readline().strip().split()
    ty = int(ty)
    x = int(x) - 1
    if ty == 1:
        k = 1<<(ord(y) - 97)
        T.update(x, k)
    else:
        y = int(y)
        Ans.append(popcount(T.query(x, y)))
print('\n'.join(map(str, Ans)))