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
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

def main():
    N,S,Q,*q = read().split()
    S = S.decode()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    for t, a, b in zip(*[iter(q)]*3):
        if t == b'1': tree.update(int(a)-1, b)
        else: print(bin(tree.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)
        size = n if n else len(initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        self.__n = 1 << ((size - 1).bit_length())
        self.__dat = [zero_factory() for _ in range(2 * self.__n)]
        if initial_values:
            zi = self.__get_leaf(0)
            for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
            for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

Solution (Python):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
def main():
    N,S,Q,*q = read().decode().split()
    N = int(N)
    S = list(S)

    c = lambda x: ord(x) - ord('a')
    tree = [SegmentTree(N, lambda x,y:x|y) for _ in range(26)]
    for i, l in enumerate(S):
        tree[c(l)].update(i, 1)

    for t, a, b in zip(*[iter(q)]*3):
        if t == '1':
            a = int(a) - 1
            tree[c(S[a])].update(a, 0)
            tree[c(b)].update(a, 1)
            S[a] = b
        else:
            a, b = int(a)-1, int(b)-1
            ans = 0
            for i in range(26):
                t = tree[i].query(a, b+1)
                ans += 1 if t else 0
            print(ans)

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

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.buffer.readline
def main():
    N = int(input())
    S = list(input().rstrip().decode())

    c = lambda x: ord(x) - ord('a')
    tree = [SegmentTree(N, lambda x,y:x|y) for _ in range(26)]
    for i, l in enumerate(S):
        tree[c(l)].update(i, 1)

    Q = int(input())
    for _ in range(Q):
        t, a, b = input().rstrip().decode().split()
        if t == '1':
            a = int(a) - 1
            tree[c(S[a])].update(a, 0)
            tree[c(b)].update(a, 1)
            S[a] = b
        else:
            a, b = int(a)-1, int(b)-1
            ans = 0
            for i in range(26):
                t = tree[i].query(a, b+1)
                ans += 1 if t else 0
            print(ans)

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

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

Solution (Python):
class SegmentTree:
    def __init__(self, initial_values, f=max, zero=0, converter=lambda x:x):
        self.__f, self.__z, self.__c, self.__size = f, zero, converter, len(initial_values)
        self.__n = 1 << ((self.__size - 1).bit_length())
        self.__dat = [zero] * (2 * self.__n)
        zi = self.__get_leaf(0)
        for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
        for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))
    
    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))
    
    def query(self, from_inclusive, to_exclusive):
        ans = self.__z
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

import sys
input = sys.stdin.readline
N = int(input())
S = input().rstrip()
tree = SegmentTree(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'))

Solution (Python):
import sys
input = sys.stdin.readline
def main():
    N = int(input())
    S = ['$'] + list(input().rstrip())

    c = lambda x: ord(x) - ord('a')
    bit = [BinaryIndexedTree(N) for _ in range(26)]
    for i, l in enumerate(S):
        if i == 0: continue
        bit[c(l)].add(i, 1)

    Q = int(input())
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1':
            a = int(a)
            bit[c(S[a])].add(a, -1)
            bit[c(b)].add(a, 1)
            S[a] = b
        else:
            a, b = int(a), int(b)
            ans = 0
            for i in range(26):
                t = bit[i].sum(b)
                if a >= 1: t -= bit[i].sum(a-1)
                ans += 1 if t else 0
            print(ans)

class BinaryIndexedTree:
    def __init__(self, n=None, f=lambda x,y:x+y, zero=0, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, = f, zero
        self.__n = n if n else len(initial_values)
        self.__dat = [zero] * (self.__n + 1)
        if initial_values:
            for i in range(1, self.__n + 1): self.add(i, initial_values[i-1]) 

    def add(self, i, v):
        while i <= self.__n:
            self.__dat[i] = self.__f(self.__dat[i], v)
            i += -i&i

    def sum(self, r):
        ans = self.__z
        while r:
            ans = self.__f(ans, self.__dat[r])
            r -= -r&r
        return ans

if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.readline
def main():
    N = int(input())
    S = list(input().rstrip())

    c = lambda x: ord(x) - ord('a')
    tree = [SegmentTree(N, lambda x,y:x|y) for _ in range(26)]
    for i, l in enumerate(S):
        tree[c(l)].update(i, 1)

    Q = int(input())
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1':
            a = int(a) - 1
            tree[c(S[a])].update(a, 0)
            tree[c(b)].update(a, 1)
            S[a] = b
        else:
            a, b = int(a)-1, int(b)-1
            ans = 0
            for i in range(26):
                t = tree[i].query(a, b+1)
                ans += 1 if t else 0
            print(ans)

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

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

Solution (Python):
def main():
    N = int(input())
    S = ['$'] + list(input())

    c = lambda x: ord(x) - ord('a')
    bit = [BinaryIndexedTree(N) for _ in range(26)]
    for i, l in enumerate(S):
        if i == 0: continue
        bit[c(l)].add(i, 1)

    Q = int(input())
    for _ in range(Q):
        t, a, b = input().split()
        if t == '1':
            a = int(a)
            bit[c(S[a])].add(a, -1)
            bit[c(b)].add(a, 1)
            S[a] = b
        else:
            a, b = int(a), int(b)
            ans = 0
            for i in range(26):
                t = bit[i].sum(b)
                if a >= 1: t -= bit[i].sum(a-1)
                ans += 1 if t else 0
            print(ans)

class BinaryIndexedTree:
    def __init__(self, n=None, f=lambda x,y:x+y, zero=0, initial_values=None):
        assert(n or initial_values)
        self.__f, self.__z, = f, zero
        self.__n = n if n else len(initial_values)
        self.__dat = [zero] * (self.__n + 1)
        if initial_values:
            for i in range(1, self.__n + 1): self.add(i, initial_values[i-1]) 

    def add(self, i, v):
        while i <= self.__n:
            self.__dat[i] = self.__f(self.__dat[i], v)
            i += -i&i

    def sum(self, r):
        ans = self.__z
        while r:
            ans = self.__f(ans, self.__dat[r])
            r -= -r&r
        return ans

if __name__ == '__main__':
    main()

Solution (Python):

class SegTree:
    def segfunc(self, x, y):
        return max(x,y)

    def __init__(self, init_val):
        
        
        self.ide_ele = 0
        n = len(init_val)
        
        self.num =2**(n-1).bit_length()
        self.seg=[self.ide_ele]*2*self.num
        for i in range(n):
            self.seg[i+self.num-1]=init_val[i]    
        
        for i in range(self.num-2,-1,-1) :
            self.seg[i]=self.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:
            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



N = int(input())

S = list(input())
ALPHAS = [[0] * (N+1) for i in range(26)]
alpha2num = lambda c: ord(c) - ord('a')
for i in range(N):
    ALPHAS[alpha2num(S[i])][i] = 1
for i,alpha in enumerate(ALPHAS):
    ALPHAS[i] = SegTree(alpha)
ALPHAS = tuple(ALPHAS)
Q = int(input())
for _ in range(Q):
    q,a,b = map(lambda c:c,input().split())
    if q == '2':
        l = int(a)-1
        r = int(b)
        ans = 0
        for i in range(26):
            ans += ALPHAS[i].query(l,r)
        print(ans)
    if q == '1':
        i = int(a)-1
        p_s = S[i]
        s = b
        S[i] = s
        ALPHAS[alpha2num(p_s)].update(i,0)
        ALPHAS[alpha2num(s)].update(i,1)

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

    n = int(input().rstrip('\n'))
    s = input().rstrip('\n')
    q = int(input().rstrip('\n'))
    Q = []

    for _ in range(q):
        Q.append(input().rstrip().split())

    class SegTree():
        def __init__(self, n_):
            self.n = 1
            while self.n < n_:
                self.n *= 2
            self.tree = []
            for _ in range(2 * self.n - 1):
                self.tree.append(2)
        def update(self, k, a):
            k += self.n - 1
            self.tree[k] = a
            while k > 0:
                k = (k - 1) // 2
                self.tree[k] = min(self.tree[k * 2 + 1], self.tree[k * 2 + 2])
        def query(self, l, r):
            l += self.n - 1
            r += self.n - 2
            res = 2
            while r-l>1:
                if l&1 == 0:
                    res = min(res,self.tree[l])
                if r&1 == 1:
                    res = min(res,self.tree[r])
                    r -= 1
                l = l//2
                r = (r-1)//2
            if l == r:
                res = min(res,self.tree[l])
            else:
                res = min(min(res,self.tree[l]),self.tree[r])
            return res

    d = { c: SegTree(n) for c in "abcdefghijklmnopqrstuvwxyz"}
    l = []

    for i, c in enumerate(s):
        d[c].update(i, 1)
        l.append(c)

    for a, b, c in Q:
        if a == "1":
            b = int(b) - 1
            d[l[b]].update(b, 2)
            d[c].update(b, 1)
            l[b] = c
        else:
            res = 0
            b, c = int(b), int(c)
            for key in d:
                if d[key].query(b-1, c) == 1:
                    res += 1
            print(res)


if __name__ == '__main__':
    main()

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

n = int(input().rstrip('\n'))
s = input().rstrip('\n')
q = int(input().rstrip('\n'))
Q = []

for _ in range(q):
    Q.append(input().rstrip().split())

class SegTree():
    def __init__(self, n_):
        self.n = 1
        while self.n < n_:
            self.n *= 2
        self.tree = []
        for _ in range(2 * self.n - 1):
            self.tree.append(2)
    def update(self, k, a):
        k += self.n - 1
        self.tree[k] = a
        while k > 0:
            k = (k - 1) // 2
            self.tree[k] = min(self.tree[k * 2 + 1], self.tree[k * 2 + 2])
    def query(self, l, r):
        l += self.n - 1
        r += self.n - 2
        res = 2
        while r-l>1:
            if l&1 == 0:
                res = min(res,self.tree[l])
            if r&1 == 1:
                res = min(res,self.tree[r])
                r -= 1
            l = l//2
            r = (r-1)//2
        if l == r:
            res = min(res,self.tree[l])
        else:
            res = min(min(res,self.tree[l]),self.tree[r])
        return res

d = { c: SegTree(n) for c in "abcdefghijklmnopqrstuvwxyz"}
l = []

for i, c in enumerate(s):
    d[c].update(i, 1)
    l.append(c)

for a, b, c in Q:
    if a == "1":
        b = int(b) - 1
        d[l[b]].update(b, 2)
        d[c].update(b, 1)
        l[b] = c
    else:
        res = 0
        b, c = int(b), int(c)
        for key in d:
            if d[key].query(b-1, c) == 1:
                res += 1
        print(res)

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

n = int(input().rstrip('\n'))
s = input().rstrip('\n')
l = [c for c in s]
q = int(input().rstrip('\n'))
Q = [input().rstrip('\n').split() for _ in range(q)]

class SegTree():
    def __init__(self, n_):
        self.n = 1
        while self.n < n_:
            self.n *= 2
        self.tree = [2 for _ in range(2 * self.n - 1)]
    def update(self, k, a):
        k += self.n - 1
        self.tree[k] = a
        while k > 0:
            k = (k - 1) // 2
            self.tree[k] = min(self.tree[k * 2 + 1], self.tree[k * 2 + 2])
    def query(self, l, r):
        l += self.n - 1
        r += self.n - 2
        res = 2
        while r-l>1:
            if l&1 == 0:
                res = min(res,self.tree[l])
            if r&1 == 1:
                res = min(res,self.tree[r])
                r -= 1
            l = l//2
            r = (r-1)//2
        if l == r:
            res = min(res,self.tree[l])
        else:
            res = min(min(res,self.tree[l]),self.tree[r])
        return res

d = { c: SegTree(n) for c in "abcdefghijklmnopqrstuvwxyz"}

for i, c in enumerate(s):
    d[c].update(i, 1)


for a, b, c in Q:
    if a == "1":
        b = int(b) - 1
        d[l[b]].update(b, 2)
        d[c].update(b, 1)
        l[b] = c
    else:
        res = 0
        b, c = int(b), int(c)
        for key in d:
            if d[key].query(b-1, c) == 1:
                res += 1
        print(res)

Solution (Python):
import math

n = int(input())
s = input()
S = [ord(i) - 97 for i in s]
q = int(input())
HEIGHT = math.ceil(math.log(n) / math.log(2))
SIZE = 1 << HEIGHT

def build_tree():
    tree = [0 for _ in range(SIZE<<1)]

    for i, letter in enumerate(s):
        tree[i+SIZE] = 1<<(ord(letter)-97)

    for i in range(HEIGHT - 1, -1, -1):
        for x in range(1<<i, 2<<i):
            tree[x] = tree[x<<1] | tree[(x<<1)+1]

    return tree




def update(x, number):
    tree[x] = number
    while x > 1:
        x >>= 1
        tree[x] = tree[x << 1] | tree[(x << 1) + 1]


def query(l, r):
    total = 0
    while l < r:
        if l&1:
            total |= tree[l]
            l += 1
        l >>= 1
        if r&1:
            r -= 1
            total |= tree[r]
        r >>= 1
    return bin(total).count('1')



tree = build_tree()

for i in range(q):
    a, b, c = input().split()
    b = int(b) - 1
    if int(a) == 1:
        update(b + SIZE, S[b])
        c = 1 << (ord(c) - 97)
        S[b] = c
        update(b + SIZE, c)
    else:
        print(query(b + SIZE, int(c)+SIZE))

Solution (Python):
class segmentTreeOR():
    initValue = 0
    dat = []
    lenTreeList = -1
    depthTreeList = 0
    lenOriginalList = -1

    def __init__(self):
        pass

    def load(self, l):
        
        self.lenOriginalList = len(l)
        self.lenTreeList = 2 ** (len(l) - 1).bit_length()  
        self.depthTreeList = (len(l) - 1).bit_length()  
        self.dat = [self.initValue] * (self.lenTreeList * 2)
        
        for i in range(len(l)):
            self.dat[self.lenTreeList - 1 + i] = l[i]
        self.build()

    def build(self):
        for i in range(self.lenTreeList - 2, -1, -1):
            self.dat[i] = self.dat[2 * i + 1] | self.dat[2 * i + 2]

    def setValue(self, i, a):
        """
        set a to list[i]
        """
        
        nodeId = (self.lenTreeList - 1) + i
        
        self.dat[nodeId] = a
        while nodeId != 0:
            nodeId = (nodeId - 1) // 2
            
            self.dat[nodeId] = self.dat[nodeId * 2 + 1] | self.dat[nodeId * 2 + 2]

    def querySub(self, a, b, nodeId, l, r):
        """
        [a,b) 区間の親クエリに対するノードnodeへ[l, r)の探索をデリゲート
        区間については、dataの添え字は0,1,2,3,4としたときに、
        [0,3)なら0,1,2の結果を返す
        """
        
        if (r <= a or b <= l):
            return self.initValue
        if a <= l and r <= b:
            return self.dat[nodeId]
        resLeft = self.querySub(a, b, 2 * nodeId + 1, l, (l + r) // 2)
        resRight = self.querySub(a, b, 2 * nodeId + 2, (l + r) // 2, r)
        return resLeft | resRight

    def query(self, a, b):
        return self.querySub(a, b, 0, 0, self.lenTreeList)



n = int(input())
s = input()
sl = list(s)
sl = list(map(lambda x: ord(x) - ord("a"), sl))
l = list(map(lambda x: 1 << x, sl))
st = segmentTreeOR()
st.load(l)

q = int(input())
for _ in range(q):
    ty, x, y = input().split()
    x = int(x)
    if ty == "1":
        nind = ord(y[0]) - ord("a") 
        st.setValue(x-1, 1 << nind)
    elif ty == "2":
        x = int(x) - 1 
        y = int(y)  
        res = 0
        cnt = st.query(x, y)
        print(bin(cnt).count("1")) 
    else:
        print("error")

Solution (Python):
class segmentTreeOR():
    initValue = 0
    dat = []
    lenTreeList = -1
    depthTreeList = 0
    lenOriginalList = -1

    def __init__(self):
        pass

    def load(self, l):
        
        self.lenOriginalList = len(l)
        self.lenTreeList = 2 ** (len(l) - 1).bit_length()  
        self.depthTreeList = (len(l) - 1).bit_length()  
        self.dat = [self.initValue] * (self.lenTreeList * 2)
        
        for i in range(len(l)):
            self.dat[self.lenTreeList - 1 + i] = l[i]
        self.build()

    def build(self):
        for i in range(self.lenTreeList - 2, -1, -1):
            self.dat[i] = self.dat[2 * i + 1] | self.dat[2 * i + 2]

    def setValue(self, i, a):
        """
        set a to list[i]
        """
        
        nodeId = (self.lenTreeList - 1) + i
        
        self.dat[nodeId] = a
        while nodeId != 0:
            nodeId = (nodeId - 1) // 2
            
            self.dat[nodeId] = self.dat[nodeId * 2 + 1] | self.dat[nodeId * 2 + 2]

    def querySub(self, a, b, nodeId, l, r):
        """
        [a,b) 区間の親クエリに対するノードnodeへ[l, r)の探索をデリゲート
        区間については、dataの添え字は0,1,2,3,4としたときに、
        [0,3)なら0,1,2の結果を返す
        """
        
        if (r <= a or b <= l):
            return self.initValue
        if a <= l and r <= b:
            return self.dat[nodeId]
        resLeft = self.querySub(a, b, 2 * nodeId + 1, l, (l + r) // 2)
        resRight = self.querySub(a, b, 2 * nodeId + 2, (l + r) // 2, r)
        return resLeft | resRight

    def query(self, a, b):
        return self.querySub(a, b, 0, 0, self.lenTreeList)



n = int(input())
s = input()
sl = list(s)
sl = list(map(lambda x: ord(x) - ord("a"), sl))
l = list(map(lambda x: 1 << x, sl))
st = segmentTreeOR()
st.load(l)

q = int(input())
for _ in range(q):
    ty, x, y = input().split()
    x = int(x)
    if ty == "1":
        nind = ord(y[0]) - ord("a") 
        st.setValue(x-1, 1 << nind)
    elif ty == "2":
        x = int(x) - 1 
        y = int(y)  
        res = 0
        cnt = st.query(x, y)
        print(bin(cnt).count("1")) 
    else:
        print("error")

Solution (Python):



import sys
read = sys.stdin.readline


def read_a_int():
    return int(read())


class SegmentTree:
    def __init__(self, ls: list, segfunc, identity_element):
        '''
        セグ木 (下書き)
        一次元のリストlsを受け取り初期化する。O(len(ls))
        区間のルールはsegfuncによって定義される
        identity elementは単位元。e.g., 最小値を求めたい→inf, 和→0, 積→1, gcd→0
        [単位元](https://ja.wikipedia.org/wiki/%E5%8D%98%E4%BD%8D%E5%85%83)
        '''
        self.ide = identity_element
        self.func = segfunc
        n = len(ls)
        self.num = 2 ** (n - 1).bit_length()  
        self.tree = [self.ide] * (2 * self.num - 1)  
        for i, l in enumerate(ls):  
            self.tree[i + self.num - 1] = l
        for i in range(self.num - 2, -1, -1):  
            self.tree[i] = segfunc(self.tree[2 * i + 1], self.tree[2 * i + 2])

    def update(self, i, x):
        '''
        i番目の要素をxに変更する(木の中間ノードも更新する) O(logN)
        '''
        i += self.num - 1
        self.tree[i] = x
        while i:  
            i = (i - 1) // 2
            self.tree[i] = self.func(self.tree[i * 2 + 1],
                                     self.tree[i * 2 + 2])

    def query(self, l, r):
        '''
        区間[l,r)に対するクエリをO(logN)で処理する。例えばその区間の最小値、最大値、gcdなど
        '''
        if r <= l:
            return ValueError('invalid index (l,rがありえないよ)')
        l += self.num - 1
        r += self.num - 2  
        res = self.ide
        while r - l > 1:  
            if l & 1 == 0:
                res = self.func(res, self.tree[l])
            if r & 1 == 1:
                res = self.func(res, self.tree[r])
                r -= 1
            l = l // 2  
            r = (r - 1) // 2  
        if l == r:
            res = self.func(res, self.tree[l])
        else:
            res = self.func(res, self.tree[l])
            res = self.func(res, self.tree[r])
        return res


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


def moji_to_bit(a):
    return 1 << (ord(a) - ord('a'))


def bit_to_sum(n):
    return sum([(n >> i) & 1 for i in range(n.bit_length())])


N = read_a_int()
S = read()[:-1]
S_bit = [moji_to_bit(s) for s in S]


st = SegmentTree(S_bit, segfunc, 0)

Q = read_a_int()
for q in range(Q):
    com, a, b = read().split()
    if int(com) == 1:
        i, c = int(a) - 1, b
        st.update(i, moji_to_bit(c))
    else:
        l, r = int(a) - 1, int(b)
        print(bit_to_sum(st.query(l, r)))