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):
class SegTree:
    def __init__(self, init_val, ide_ele, segfunc):
        self.n = len(init_val)
        self.num =2**(self.n-1).bit_length()
        self.ide_ele = ide_ele
        self.seg = [self.ide_ele]*2*self.num
        self.segfunc = segfunc
        
        
        for i in range(self.n):
            self.seg[i+self.num-1] = init_val[i]    
        
        for i in range(self.num-2,-1,-1) :
            self.seg[i] = segfunc(self.seg[2*i+1], self.seg[2*i+2]) 
    
    def update(self, k, x):
        k += self.num-1
        self.seg[k] = x
        while k+1:
            k = (k-1)//2
            self.seg[k] = self.segfunc(self.seg[k*2+1], self.seg[k*2+2])
    
    def query(self, p, q):
        if q<=p:
            return self.ide_ele
        p += self.num-1
        q += self.num-2
        res = self.ide_ele
        while q-p>1:
            if p&1 == 0:
                res = self.segfunc(res, self.seg[p])
            if q&1 == 1:
                res = self.segfunc(res, self.seg[q])
                q -= 1
            p = p//2
            q = (q-1)//2
        if p == q:
            res = self.segfunc(res, self.seg[p])
        else:
            res = self.segfunc(self.segfunc(res, self.seg[p]), self.seg[q])
        return res
    
import sys
input = sys.stdin.readline
N = int(input())
S = input()
L = [-1]*N
for i in range(N):
    L[i] = 2**(ord(S[i]) - ord('a'))
    
def segfunc(a,b):
    return a | b

Seg = SegTree(L,0,segfunc)

Q = int(input())

for _ in range(Q):
    q,a,b = input().split()
    if q == '1':
        i = int(a)-1
        c = 2**(ord(b) - ord('a'))
        Seg.update(i,c)
    elif q=='2':
        l = int(a)-1
        r = int(b)-1
        X = Seg.query(l,r+1)
        tmp = 0
        for j in range(30):
            if X%2==1:
                tmp += 1
            X//=2
        print(tmp)

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


class SegTree():
    def __init__(self, N, e=float("inf"), operator_func=min):
        self.e = e
        self.size = N
        self.node = [self.e] * (2*N)
        self.op = operator_func

    def set_list(self, l):
        for i in range(self.size):
            self.node[i+self.size-1] = l[i]
        for i in range(self.size-1)[::-1]:
            self.node[i] = self.op(self.node[2*i+1], self.node[2*i+2])
    
    def update(self, k, x):
        k += self.size - 1
        self.node[k] = x
        while k >= 0:
            k = (k - 1) // 2
            self.node[k] = self.op(self.node[2*k+1], self.node[2*k+2])

    def get(self, l, r):
        x = self.e
        l += self.size; r += self.size
        a, b = [], []

        while l<r:
            if l&1:
                a += [l-1]; l += 1
            if r&1:
                r -= 1; b += [r-1]
            l >>= 1; r >>= 1

        for i in a+(b[::-1]):
            x = self.op(x, self.node[i])
        return x


def main():
    N = int(input())
    S = list(input())[:-1]
    trees = {chr(97+i):SegTree(N, e=0, operator_func=or_) for i in range(26)}

    for i, s in enumerate(S):
        trees[s].update(i, 1)

    Q = int(input())
    for _ in range(Q):
        mode, i, v = input().split()
        if mode=="1":
            i = int(i)-1
            trees[S[i]].update(i, 0)
            trees[v].update(i, 1)
            S[i] = v
        else:
            i = int(i)-1
            v = int(v)
            ans = sum(trees[chr(97+j)].get(i, v) for j in range(26))
            print(ans)


if __name__ == "__main__":
    main()

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


class SegTree():
    def __init__(self, N, e=float("inf"), operator_func=min):
        self.e = e
        self.size = N
        self.node = [self.e] * (2*N)
        self.op = operator_func

    def set_list(self, l):
        for i in range(self.size):
            self.node[i+self.size-1] = l[i]
        for i in range(self.size-1)[::-1]:
            self.node[i] = self.op(self.node[2*i+1], self.node[2*i+2])
    
    def update(self, k, x):
        k += self.size - 1
        self.node[k] = x
        while k >= 0:
            k = (k - 1) // 2
            self.node[k] = self.op(self.node[2*k+1], self.node[2*k+2])

    def get(self, l, r):
        x = self.e
        l += self.size; r += self.size
        a, b = [], []

        while l<r:
            if l&1:
                a += [l-1]; l += 1
            if r&1:
                r -= 1; b += [r-1]
            l >>= 1; r >>= 1

        for i in a+(b[::-1]):
            x = self.op(x, self.node[i])
        return x


def main():
    N = int(input())
    S = list(input())[:-1]
    trees = {chr(97+i):SegTree(N, e=False, operator_func=or_) for i in range(26)}

    for i, s in enumerate(S):
        trees[s].update(i, True)

    Q = int(input())
    for _ in range(Q):
        mode, i, v = input().split()
        if mode=="1":
            i = int(i)-1
            trees[S[i]].update(i, False)
            trees[v].update(i, True)
            S[i] = v
        else:
            i = int(i)-1
            v = int(v)
            ans = 0
            for j in range(26):
                ans += trees[chr(97+j)].get(i, v)
            print(ans)


if __name__ == "__main__":
    main()

Solution (Python):
import sys
 
def main():
    input = sys.stdin.readline
    N = int(input())
    S = input().rstrip()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    Q = int(input())
    update = tree.update
    query = tree.query
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))    

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        size = n if n else len(initial_values)
        self.__n = 1 << ((size - 1).bit_length())
        d = [zero_factory() for _ in range(2 * self.__n + 1)]
        self.__dat = d
        if initial_values:
            for i, v in enumerate(initial_values): d[self.__n + i] = converter(v)
            for i in range(self.__n - 1, 0, -1): d[i] = f(d[i<<1], d[i<<1|1])

    def update(self, index, value):
        i, v, d, f = index + self.__n, self.__c(value), self.__dat, self.__f
        if d[i] == v: return
        d[i] = v
        while i:
            i = i >> 1
            d[i] = f(d[i<<1], d[i<<1|1])

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r, d, f = from_inclusive + self.__n, to_exclusive + self.__n, self.__dat, self.__f
        while l < r:
            if l & 1: ans, l = f(ans, d[l]), l+1
            if r & 1: ans, r = f(ans, d[r-1]), r-1
            l, r = l >> 1, r >> 1
        return ans

if __name__ == '__main__':
    main()

Solution (Python):
import sys
 
def main():
    input = sys.stdin.readline
    N = int(input())
    S = input().rstrip()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    Q = int(input())
    update = tree.update
    query = tree.query
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))    

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        size = n if n else len(initial_values)
        self.__n = 1 << ((size - 1).bit_length())
        d = [zero_factory() for _ in range(2 * self.__n + 1)]
        self.__dat = d
        if initial_values:
            for i, v in enumerate(initial_values): d[self.__n + i] = converter(v)
            for i in range(self.__n - 1, 0, -1): d[i] = f(d[i<<1], d[i<<1|1])

    def update(self, index, value):
        i, v, d = index + self.__n, self.__c(value), self.__dat
        if d[i] == v: return
        d[i] = v
        while i:
            i = i >> 1
            d[i] = self.__f(d[i<<1], d[i<<1|1])

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = from_inclusive + self.__n, to_exclusive + self.__n
        while l < r:
            if l & 1: ans, l = self.__f(ans, self.__dat[l]), l+1
            if r & 1: ans, r = self.__f(ans, self.__dat[r-1]), r-1
            l, r = l >> 1, r >> 1
        return ans

if __name__ == '__main__':
    main()

Solution (Python):
def main():
    N = int(input())
    S = input()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    Q = int(input())
    update = tree.update
    query = tree.query
    for _ in range(Q):
        t, a, b = input().split()
        if t == '1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))    

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        size = n if n else len(initial_values)
        self.__n = 1 << ((size - 1).bit_length())
        d = [zero_factory() for _ in range(2 * self.__n + 1)]
        self.__dat = d
        if initial_values:
            for i, v in enumerate(initial_values): d[self.__n + i] = converter(v)
            for i in range(self.__n - 1, 0, -1): d[i] = f(d[i<<1], d[i<<1|1])

    def update(self, index, value):
        i, v, d = index + self.__n, self.__c(value), self.__dat
        if d[i] == v: return
        d[i] = v
        while i:
            i = i >> 1
            d[i] = self.__f(d[i<<1], d[i<<1|1])

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = from_inclusive + self.__n, to_exclusive + self.__n
        while l < r:
            if l & 1: ans, l = self.__f(ans, self.__dat[l]), l+1
            if r & 1: ans, r = self.__f(ans, self.__dat[r-1]), r-1
            l, r = l >> 1, r >> 1
        return ans

if __name__ == '__main__':
    main()

Solution (Python):
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines


def string_to_number(a):
    return 1 << (ord(a) - 97)

class SegmentTree:
    """
    セグ木は 1-indexed
    """
    def __init__(self, n, initial=0):
        self.offset = 2**(n-1).bit_length()
        self.initial = initial
        self.seg = [self.initial] * (2 * self.offset)


    def build(self, A):
        """
        A: 処理したい配列
        """
        for i, a in enumerate(A, start=self.offset):
            self.seg[i] = string_to_number(a)
        for i in range(self.offset-1,0,-1):
            self.seg[i] = self.seg[i<<1] | self.seg[(i<<1)+1]

            
    def update(self, k, a):
        k += self.offset
        self.seg[k] = string_to_number(a)
        while k:
            k >>= 1
            self.seg[k] = self.seg[k<<1] | self.seg[(k<<1)+1]

            
    def query(self, a, b):
        a += self.offset
        b += self.offset
        res = self.initial
        while a < b:
            if a & 1:
                res |= self.seg[a]
                a += 1
            if b & 1:
                res |= self.seg[b-1]
            a >>= 1
            b >>= 1
        
        return bin(res).count("1")


def main():
    N,s,Q,*q = read().split()
    seg = SegmentTree(int(N))
    seg.build(s)
    

    for t, a, b in zip(*[iter(q)]*3):
        if t == "1":
            seg.update(int(a)-1, b)
        else:
            print(seg.query(int(a)-1, int(b)))


if __name__ == "__main__":
    main()

Solution (Python):

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


def string_to_number(a):
    return 1 << (ord(a) - 97)

class SegmentTree:
    def __init__(self, A):
        self.n = 2**(len(A)-1).bit_length()
        self.identity = 0
        self.seg = [self.identity] * (2 * self.n)
        
        for i, a in enumerate(A):
            self.seg[self.n-1+i] = string_to_number(a)
        for i in range(self.n-2,-1,-1):
            self.seg[i] = self.seg[2*i+1] | self.seg[2*i+2]

            
    def update(self, k, a):
        k += self.n - 1
        self.seg[k] = string_to_number(a)
        while k:
            k = (k - 1) // 2
            self.seg[k] = self.seg[k*2+1] | self.seg[k*2+2]

            
    def query(self, a, b):
        if b == a:
        	return 1
        a += self.n - 1
        b += self.n - 2
        res = self.identity
        while b - a > 1:
            if not a & 1:
                res |= self.seg[a]
            if b & 1:
                res |= self.seg[b]
                b -= 2
            a >>= 1
            b -= 1
            b >>= 1
        if a == b:
            res |= self.seg[a]
        else:
            res |= (self.seg[a] | self.seg[b])
        
        return bin(res).count("1")


def main():
    N = int(readline())
    s = readline().strip()
    seg = SegmentTree(list(s))

    Q = int(readline())
    q = map(str, read().split())
    ans = []
    for t, a, b in zip(*[iter(q)]*3):
        if t == "1":
            seg.update(int(a)-1, b)
        else:
            ans.append(seg.query(int(a)-1, int(b)))
    
    print("\n".join(map(str, ans)))


if __name__ == "__main__":
    main()

Solution (Python):
class SegmentTree():
    """
    update, get を提供するSegmentTree

    Attributes
    ----------
    __n : int
        葉の数。2 ^ i - 1
    __dot :
        Segment function
    __e: int
        単位元
    __node: list
        Segment Tree
    """
    def __init__(self, A, dot, e):
        """
        Parameters
        ----------
        A : list
            対象の配列
        dot :
            Segment function
        e : int
            単位元
        """
        n = 2 ** (len(A) - 1).bit_length()
        self.__n = n
        self.__dot = dot
        self.__e = e
        self.__node = [e] * (2 * n)
        for i in range(len(A)):
            self.__node[i + n] = A[i]
        for i in range(n - 1, 0, -1):
            self.__node[i] = self.__dot(self.__node[2 * i], self.__node[2 * i + 1])
    
    def update(self, i, c):
        i += self.__n
        node = self.__node
        node[i] = c
        while i > 0:
            i //= 2
            node[i] = self.__dot(node[2 * i], node[2 * i + 1])

    def get(self, l, r):
        vl, vr = self.__e, self.__e
        l += self.__n
        r += self.__n
        while (l < r):
            if l & 1:
                vl = self.__dot(vl, self.__node[l])
                l += 1
            l //= 2
            if r & 1:
                r -= 1
                vr = self.__dot(vr, self.__node[r])
            r //= 2
        return self.__dot(vl, vr)


def solve():
    import sys
    from operator import add
    N = int(input())
    S = list(input())
    Q = int(input())
    Query = sys.stdin.readlines()

    a = ord('a')
    A = [[0] * N for _ in range(26)]
    for i, s in enumerate(S):
        s = ord(s) - a
        A[s][i] = 1
    seg = [SegmentTree(A[i], add, 0) for i in range(26)]

    for i in range(Q):
        t, x, y = Query[i].split()
        t = int(t)
        x = int(x) - 1
        if t == 1 and S[x] != y:
            c = S[x]
            S[x] = y
            seg[ord(c) - a].update(x, 0)
            seg[ord(y) - a].update(x, 1)
            continue
        elif t == 2:
            y = int(y) - 1
            ans = 0
            for j in range(26):
                ans += (seg[j].get(x, y + 1)) > 0
            print(ans)


solve()

Solution (Python):
import bisect

n=int(input())
s=list(input())


alpha={chr(i):[] for i in range(97,123)}


for i,c in enumerate(s):
    bisect.insort(alpha[c],i+1)

for i in range(int(input())):
    p,q,r=input().split()
    if p=='1':
        q=int(q)
        b=s[q-1]
        if b!=r:
            alpha[b].pop(bisect.bisect_left(alpha[b],q))
            bisect.insort(alpha[r],q)
            s[q-1]=r
    else:
        count=0
        for l in alpha.values():
            pos=bisect.bisect_left(l,int(q))
            if pos<len(l) and l[pos]<=int(r):
                count+=1
        print(count)

Solution (Python):
def main():
    n = int(input())
    s = input()
    Q = int(input())
    t = [input().split() for _ in range(Q)]

    d = [0] * n + [1 << ord(c) - 97 for c in s]
    for i in range(n - 1, 0, -1):
        d[i] = d[i + i] | d[i - ~i]
    for q, a, b in t:
        i, s = int(a) + n - 1, 0
        if q < "2":
            d[i] = 1 << ord(b) - 97
            while i > 1:
                i //= 2
                d[i] = d[i + i] | d[i - ~i]
        else:
            j = int(b) + n
            while i < j:
                if i & 1:
                    s |= d[i]
                    i += 1
                if j & 1:
                    j -= 1
                    s |= d[j]
                i //= 2
                j //= 2
            print(bin(s).count("1"))


main()

Solution (Python):
import bisect
n=int(input())
s=list(input())
a={chr(i):[] for i in range(97,123)}
for i,c in enumerate(s):
    bisect.insort(a[c],i+1)
for i in range(int(input())):
    p,q,r=list(map(str,input().split()))
    if p=="1":
        q=int(q)
        b=s[q-1]
        if b!=r:
            a[b].pop(bisect.bisect_left(a[b],q))
            bisect.insort(a[r],q)
            s[q-1]=r
    else:
        d=0
        for l in a.values():
            g=bisect.bisect_left(l,int(q))
            if g<len(l) and l[g]<=int(r):
                d+=1
        print(d)

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

data=[0]*(2*n)
def upd(i,x):
  i+=n
  data[i]=x
  while i>1:
    data[i>>1]=data[i]|data[i^1]
    i>>=1
def qry(l,r):
  l+=n
  r+=n
  res=0
  while l<r:
    if l&1:
      res|=data[l]
      l+=1
    if r&1:
      r-=1
      res|=data[r]
    l>>=1
    r>>=1
  return bin(res).count('1')

for i,c in enumerate(input()[:-1],n):
  data[i]=1<<(ord(c)-ord('a'))
for i in range(n-1,0,-1):
  data[i]=data[i<<1]|data[i<<1|1]
ans=[]
for _ in range(int(input())):
  q,a,b=input().split()
  if int(q)==1:
    upd(int(a)-1,1<<(ord(b)-ord('a')))
  else:
    ans.append(qry(int(a)-1,int(b)))
print('\n'.join(map(str,ans)))

Solution (Python):
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines


def string_to_number(a):
    return 1 << (ord(a) - 97)

class SegmentTree:
    def __init__(self, A):
        self.n = 2**(len(A)-1).bit_length()
        self.identity = 0
        self.seg = [self.identity] * (2 * self.n)
        
        for i, a in enumerate(A):
            self.seg[self.n-1+i] = string_to_number(a)
        for i in range(self.n-2,-1,-1):
            self.seg[i] = self.seg[2*i+1] | self.seg[2*i+2]

            
    def update(self, k, a):
        k += self.n - 1
        self.seg[k] = string_to_number(a)
        while k:
            k = (k - 1) // 2
            self.seg[k] = self.seg[k*2+1] | self.seg[k*2+2]

            
    def query(self, a, b):
        if b == a:
        	return 1
        a += self.n - 1
        b += self.n - 2
        res = self.identity
        while b - a > 1:
            if not a & 1:
                res |= self.seg[a]
            if b & 1:
                res |= self.seg[b]
                b -= 2
            a >>= 1
            b -= 1
            b >>= 1
        if a == b:
            res |= self.seg[a]
        else:
            res |= (self.seg[a] | self.seg[b])
        
        return bin(res).count("1")


def main():
    N = int(readline())
    s = readline().strip()
    seg = SegmentTree(list(s))
    

    Q = int(readline())
    q = map(str, read().split())
    for t, a, b in zip(*[iter(q)]*3):
        if t == "1":
            seg.update(int(a)-1, b)
        else:
            print(seg.query(int(a)-1, int(b)))


if __name__ == "__main__":
    main()

Solution (Python):

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

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

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

n = int(input())
s = input()
q = int(input())

bit = [BIT(n+1) for i in range(26)]
for i in range(n):
    bit[ord(s[i])-97].add(i+1, 1)


s = list(s)
for _ in range(q):
    query, a, b = input().split()
    if query == "1":
        i = int(a)
        c = ord(b)-97
        bit[c].add(i, 1)

        bit[ord(s[i-1])-97].add(i, -1)
        s[i-1] = b
    else:
        ans = 0
        for k in range(26):
            if bit[k].sum(int(b))-bit[k].sum(int(a)-1) >= 1:
                ans += 1
        print(ans)

Solution (Python):

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

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

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

n = int(input())
s = input()
q = int(input())

bit = [BIT(n+1) for i in range(26)]
for i in range(n):
    bit[ord(s[i])-97].add(i+1, 1)


s = list(s)
for _ in range(q):
    query, a, b = input().split()
    if query == "1":
        i = int(a)
        c = ord(b)-97
        bit[ord(s[i-1])-97].add(i, -1)
        bit[c].add(i, 1)
        s[i-1] = b
    else:
        ans = 0
        for k in range(26):
            if bit[k].sum(int(b))-bit[k].sum(int(a)-1) >= 1:
                ans += 1
        print(ans)

Solution (Python):
import math
from functools import reduce
from collections import deque
import sys
sys.setrecursionlimit(10**7)
import bisect


def get_nums_l():
    return [ int(s) for s in input().split(" ")]


def get_nums_n(n):
    return [ int(input()) for _ in range(n)]


def get_all_int():
    return map(int, open(0).read().split())

def log(*args):
    print("DEBUG:", *args, file=sys.stderr)

class segtree:

    def __init__(self, n,operator,identity):
        nb = bin(n)[2:]
        bc = sum([int(digit) for digit in nb])
        if bc == 1:
            self.num_end_leaves = 2**(len(nb)-1)
        else:
            self.num_end_leaves = 2**(len(nb))

        self.array = [identity for i in range(self.num_end_leaves * 2)]
        self.identity = identity
        self.operator =operator

    def update(self,x,val):
        actual_x = x+self.num_end_leaves
        self.array[actual_x] = val
        while actual_x > 0 :
            actual_x = actual_x//2
            self.array[actual_x] = self.operator(self.array[actual_x*2],self.array[actual_x*2+1])

    def get(self,q_left,q_right,arr_ind=1,leaf_left=0,depth=0):
        width_of_floor = self.num_end_leaves//(2**depth)
        leaf_right = leaf_left+width_of_floor-1

        if leaf_left > q_right or leaf_right < q_left:
            return  self.identity

        elif leaf_left >= q_left and leaf_right <= q_right:
            return self.array[arr_ind]

        else:
            val_l = self.get(q_left,q_right,2*arr_ind,leaf_left,depth+1)
            val_r = self.get(q_left,q_right,2*arr_ind+1,leaf_left+width_of_floor//2,depth+1)
            return self.operator(val_l,val_r)

n = int(input())
s = [ c for c in input()]
q = int(input())
qqq = list(map(lambda s: s.strip().split(), sys.stdin.readlines()))

seg = segtree(n+1, lambda a,b:a|b, 0)

for i,c in enumerate(s):
    o = ord(c) - ord("a")
    seg.update(i, 2**o)


for que in qqq:
    if que[0] == "1":
        target = int(que[1])-1
        o = ord(que[2]) - ord("a")
        seg.update(target, 2**o)

    else:
        left = int(que[1])-1
        right = int(que[2])-1

        x = seg.get(left, right)
        log("x", x)
        count = 0
        while x > 0:
            if x % 2 == 1:
                count += 1
            x = x//2
        print(count)

Solution (Python):
import bisect

n = int(input())
s = list(input())
q = int(input())

alpha_map = {chr(i):[] for i in range(97,123)}
for i,c in enumerate(s):
    bisect.insort(alpha_map[c],i+1)
    
for _ in range(q):
    x,y,z = map(str,input().split())
    if int(x) == 1:
        y = int(y)
        bef = s[y-1]
        if bef == z:
            continue
        alpha_map[bef].pop(bisect.bisect_left(alpha_map[bef],y))
        bisect.insort(alpha_map[z],y)
        s[y-1] = z
    else:
        count = 0
        for i,j in alpha_map.items():
            idx = bisect.bisect_left(j,int(y))
            if idx < len(j) and j[idx] <= int(z):
                    count += 1
        print(count)

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


if __name__ == "__main__":
    N = int(input())
    S = list(input())
    d = {x: i for i, x in enumerate("abcdefghijklmnopqrstuvwxyz")}
    BIT = [BinaryIndexTree(N) for _ in range(26)]

    
    for i, s in enumerate(S, start=1):
        BIT[d[s]].add(i, 1)

    Q = int(input())
    ans = []
    for _ in range(Q):
        query, x, y = input().split()
        if query == "1":
            i = int(x)
            c_new = y
            c_old = S[i - 1]
            BIT[d[c_new]].add(i, 1)
            BIT[d[c_old]].add(i, -1)
            S[i - 1] = c_new
        else:
            cnt = 0
            l = int(x) - 1
            r = int(y)
            for b in BIT:
                tmp = b.sum(r) - b.sum(l)
                if tmp:
                    cnt += 1
            ans.append(cnt)

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

Solution (Python):
"""SegTree, bitで集合を管理する

Returns:
    [type]: [description]
"""
import sys
sys.setrecursionlimit(4100000)

import math

import logging

logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger(__name__)

from operator import or_


class SegTree:
    """ノードで集合をもつ
    """
    def __init__(self, N, segfunc, ide, initial_list=None):

        self.ide = ide
        self.segfunc = segfunc

        
        _n = N
        self.n = 1
        while (self.n < _n):
            self.n = self.n * 2

        self.tree = [self.ide for _ in range(2 * self.n - 1)]

        if initial_list is not None:
            for i, v in enumerate(initial_list):
                self.update(i, v)

    def update(self, i, x):
        i = i + self.n - 1
        self.tree[i] = x

        
        while (i > 0):
            i = (i - 1) // 2
            l = self.tree[i * 2 + 1]
            r = self.tree[i * 2 + 2]
            self.tree[i] = self.segfunc(l, r)

    def query(
        self,
        l,
        r,  
    ):
        l += (self.n - 1)
        r += (self.n - 1)
        res = self.ide
        while l < r:
            if l & 1 == 0:  
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1 == 0:
                res = self.segfunc(res, self.tree[r - 1])
                r -= 1

            l = l // 2
            r = r // 2

        return res


def resolve():
    N = [int(x) for x in sys.stdin.readline().split()][0]  
    S = [x for x in sys.stdin.readline().split()][0]  
    Q = [int(x) for x in sys.stdin.readline().split()][0]  

    
    

    
    
    grid = [[x for x in sys.stdin.readline().split()]
            for _ in range(Q)]  

    seg = SegTree(N, or_, 0, [1 << ord(c) - 97 for c in S])

    for _type, a, b in grid:
        if _type == '1':
            a = int(a) - 1
            bit = 1 << (ord(b) - 97)
            seg.update(a, bit)

        else:
            a = int(a) - 1
            b = int(b) - 1
            ret = seg.query(a, b + 1)
            print(bin(ret)[2:].count('1'))


if __name__ == "__main__":
    resolve()





import sys
from io import StringIO
import unittest


class TestClass(unittest.TestCase):
    def assertIO(self, input, output):
        stdout, stdin = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(input)
        resolve()
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, stdin
        self.assertEqual(out, output)

    def test_入力例_1(self):
        input = """7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7"""
        output = """3
1
5"""
        self.assertIO(input, output)

    def test_入力例_2(self):
        input = """7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7"""
        output = """3
1
5"""
        self.assertIO(input, output)