Problem: 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).

Submission attempts (in order):
class SegmentTree:
    
    
    
    def __init__(self, size, f=lambda x,y : x+y, default=0):
        self.size = 2**(size-1).bit_length() 
        self.default = default
        self.dat = [default]*(self.size*2) 
        self.f = f

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

    
    def query(self, l, r):
        l += self.size
        r += self.size
        lres, rres = self.default, self.default
        while l < r:
            if l & 1:
                lres = self.f(lres, self.dat[l])
                l += 1

            if r & 1:
                r -= 1
                rres = self.f(self.dat[r], rres) 
            l >>= 1
            r >>= 1
        res = self.f(lres, rres)
        return res

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

def a2n(a):
    return ord(a)-ord("a")

def createInp(a):
    return 1 << a2n(a)

def main():
    N = int(input())
    S = input()
    Q = int(input())
    ST = SegmentTree(N, f=f, default=0)

    for i, s in enumerate(S):
        ST.update(i+1, createInp(s))

    for _ in range(Q):
        t, l, r = input().split()
        if int(t) == 1:
            ST.update(int(l), createInp(s))
        else:
            print(len(ST.query(int(l), int(r)+1)))

if __name__ == '__main__':
    main()


class SegmentTree:
    
    
    
    def __init__(self, size, f=lambda x,y : x+y, default=0):
        self.size = 2**(size-1).bit_length() 
        self.default = default
        self.dat = [default]*(self.size*2) 
        self.f = f

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

    
    def query(self, l, r):
        l += self.size
        r += self.size
        lres, rres = self.default, self.default
        while l < r:
            if l & 1:
                lres = self.f(lres, self.dat[l])
                l += 1

            if r & 1:
                r -= 1
                rres = self.f(self.dat[r], rres) 
            l >>= 1
            r >>= 1
        res = self.f(lres, rres)
        return res

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

import pysnooper

#@pysnooper.snoop()
def main():
    N = int(input())
    S = input()
    Q = int(input())
    ST = SegmentTree(N, f=f, default=set([]))

    for i, s in enumerate(S):
        ST.update(i+1, set([s]))

    for _ in range(Q):
        t, l, r = input().split()
        if int(t) == 1:
            ST.update(int(l), set([r]))
        else:
            print(len(ST.query(int(l), int(r)+1)))

if __name__ == '__main__':
    main()


class SegmentTree():
    

    def __init__(self, n, func, init=float('inf')):
        
        self.n = 2**(n-1).bit_length()
        self.init = init
        self.data = [init]*(2*self.n)
        self.func = func

    def set(self, k, v):
        
        self.data[k+self.n-1] = v

    def build(self):
        
        for k in reversed(range(self.n-1)):
            self.data[k] = self.func(self.data[k*2+1], self.data[k*2+2])

    def update(self, k, a):
        
        k += self.n-1
        self.data[k] = a

        while k > 0:
            k = (k-1)//2
            self.data[k] = self.func(self.data[k*2+1], self.data[k*2+2])

    def query(self, l, r):
        
        L = l+self.n
        R = r+self.n
        ret = self.init
        while L < R:
            if R & 1:
                R -= 1
                ret = self.func(ret, self.data[R-1])
            if L & 1:
                ret = self.func(ret, self.data[L-1])
                L += 1
            L >>= 1
            R >>= 1
        return ret

N = int(input())
S = input()
Q = int(input())
Seg = SegmentTree(N, lambda x, y: x | y, 0)

def a2n(a):
    return ord(a) - ord('a')

def createBit(a):
    return 1 << a2n(a)

for i, s in enumerate(S):
    Seg.set(i, createBit(s))
Seg.build()

for _ in range(Q):
    t, l, r = input().split()
    if int(t) == 1:
        Seg.update(int(l)-1, createBit(r))
    else:
        print(bin(Seg.query(int(l)-1, int(r))).count('1'))

# N = int(input())
# S = input()
# Q = int(input())
# queries = [list(input().split()) for _ in range(Q)]


# def a2n(a):
#     return ord(a)-ord("a")



#     return 1 << a2n(a)



# for i, s in enumerate(S):






#     else:


Verdicts: Runtime Error

Runtime Error

Accepted