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 SegmentTree(object):
    """
    セグメントツリー (0-indexed)

    1. 値の更新 O(logN)
    2. 区間クエリ O(logN)
    """
    def __BinOp(self, x, y):
        """ セグ木で使用する二項演算 """
        return x | y

    def __init__(self, init_ele, N:int):
        """
        セグ木を構築する

        init_ele: 単位元 
        N: 要素数
        """
        self.__init_ele = init_ele
        self.__n = 1
        while self.__n < N:
            self.__n <<= 1

        self.__dat = [init_ele] * (2 * self.__n)
    
    def update(self, k:int, x):
        """ k番目の値をxに変更する """
        k += self.__n - 1
        self.__dat[k] = x
        while k:
            k = (k - 1) // 2
            self.__dat[k] = self.__BinOp(
                self.__dat[k * 2 + 1], self.__dat[k * 2 + 2]
                )
    
    def query(self, p:int, q:int):
        """ 区間クエリ [p,q) """
        if q <= p: return self.__init_ele
        p += self.__n - 1
        q += self.__n - 2
        res = self.__init_ele
        while q - p > 1:
            if not (p & 1):
                res = self.__BinOp(res, self.__dat[p])
            if q & 1:
                res = self.__BinOp(res, self.__dat[q])
                q -= 1
            p = p // 2
            q = (q - 1) // 2
        res = self.__BinOp(res, self.__dat[p])
        if p != q: res = self.__BinOp(res, self.__dat[q])
        return res
    
    def get_num(self, k:int):
        """ k番目の値を取得する """
        k += self.__n - 1
        return self.__dat[k]


N = int(input())

ST = SegmentTree(0, N)
for i, s in enumerate(list(input())):
    ST.update(i, 1 << (ord(s) - ord('a')))

Q = int(input())
for _ in range(Q):
    x,y,z = map(str,input().split())
    x = int(x); y = int(y)
    if x == 1:
        ST.update(y - 1, 1 << (ord(z) - ord('a')))
    else:
        z = int(z)
        print(bin(ST.query(y - 1, z)).count("1"))

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


class RangeUpdate:
    def __init__(self, n):
        self.p = BIT(n + 1)
        self.q = BIT(n + 1)

    def add(self, s, t, x):
        t += 1
        self.p.add(s, -x * s)
        self.p.add(t, x * t)
        self.q.add(s, x)
        self.q.add(t, -x)

    def sum(self, s, t):
        t += 1
        return self.p.sum(t) + self.q.sum(t) * t - \
            self.p.sum(s) - self.q.sum(s) * s


def main():
    from string import ascii_lowercase
    dic = {s: i for i, s in enumerate(ascii_lowercase)}
    N = int(input())
    S = [s for s in input()]
    BIT26 = [RangeUpdate(N) for i in range(26)]
    for i, s in enumerate(S):
        j = dic[s]
        BIT26[j].add(i+1, i+1, 1)
    Q = int(input())
    for query in range(Q):
        A = [i for i in input().split()]
        if A[0] == "1":
            i = int(A[1])
            c = A[2]
            pre = S[i-1]
            j = dic[pre]
            BIT26[j].add(i, i, -1)
            S[i-1] = c
            j = dic[c]
            BIT26[j].add(i, i, 1)
        else:
            le = int(A[1])
            ri = int(A[2])
            ans = 0
            for i in range(26):
                if 0 < BIT26[i].sum(le, ri):
                    ans += 1
            print(ans)


if __name__ == '__main__':
    main()

Solution (Python):
def update(i,x):
    i += d-1
    bit = ord(x)-97
    seg[i] = 0 | (1<<bit)
    while i > 0:
        i = (i-1)//2
        seg[i] = seg[i*2+1]|seg[i*2+2]
def find(a,b,k,l,r):
    if r <= a or b <= l:
        return 0
    if a <= l and r <= b:
        return seg[k]
    c1 = find(a,b,2*k+1,l,(l+r)//2)
    c2 = find(a,b,2*k+2,(l+r)//2,r)
    return c1|c2
n = int(input())
s = input()
q = int(input())
d = 1
while d < n:
    d *= 2
seg = [0]*(2*d-1)
for i in range(n):
    update(i,s[i])
for i in range(q):
    type,a,b = input().split()
    if type == "1":
        update(int(a)-1,b)
    else:
        part = find(int(a)-1,int(b),0,0,d)
        print(bin(part).count("1"))

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

from bisect import bisect_left, insort_left

def main():
    n = int(readline())
    s = list(readline().rstrip())
    q = int(readline())
    
    chk_abc = [[] for i in range(26)]
    for i, si in enumerate(s):
        ci = ord(si) - 97
        chk_abc[ci].append(i)
        
    ans = []
    for _ in range(q):
        cmd, i, j = readline().rstrip().split()
        i = int(i) - 1
        
        if cmd == "1":
            if s[i] == j:
                continue
            c1 = ord(s[i]) - 97
            prev = chk_abc[c1]
            c2 = ord(j) - 97
            prev.pop(bisect_left(prev, i))
            s[i] = j
            insort_left(chk_abc[c2], i)
            
        else:
            j = int(j) - 1
            num = 0
            for chk in chk_abc:
                le = len(chk)
                k = bisect_left(chk, i, 0, le)
                if k == le:
                    continue
                if i <= chk[k] <= j:
                    num += 1
            ans.append(num)

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

if __name__ == "__main__":
    main()

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

class SegmentTree():
    def __init__(self, S, n):
        self.size = n
        self.array = [set()] * (2**(self.size + 1) - 1)
        for i, c in enumerate(S):
            self.array[i + 2**self.size - 1] = {c}
        for i in range(2**self.size - 1)[::-1]:
            self.array[i] = self.array[2 * i + 1] | self.array[2 * i + 2]

    def subquery(self, l, r, k, i, j):
        if j <= l or r <= i:
            return set()
        elif l <= i and j <= r:
            return self.array[k]
        else:
            l_set = self.subquery(l, r, 2 * k + 1, i, (i + j) // 2)
            r_set = self.subquery(l, r, 2 * k + 2, (i + j) // 2, j)
            return l_set | r_set

    def query(self, l, r):
        return len(self.subquery(l, r, 0, 0, 2**self.size))

    def update(self, i, c):
        tmp = i + 2**self.size - 1
        self.array[tmp] = {c}
        while tmp > 0:
            tmp = (tmp - 1) // 2
            self.array[tmp] = self.array[2 * tmp + 1] | self.array[2 * tmp + 2]

n = int(input())
S = [ord(c) for c in list(input())]
segtree = SegmentTree(S, 19)
for _ in range(int(input())):
    t, i, c = input().split()
    if t == '1':
        segtree.update(int(i)-1, ord(c))
    if t == '2':
        print(segtree.query(int(i)-1, int(c)))

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


class SegmentTree():
    
    def __init__(self, S, n):
        self.size = n
        self.array = [set()] * (2**(self.size + 1) - 1)
        for i, c in enumerate(S):
            self.array[i + 2**self.size - 1] = {c}
        for i in range(2**self.size - 1)[::-1]:
            self.array[i] = self.array[2 * i + 1] | self.array[2 * i + 2]

    def subquery(self, l, r, k, i, j):
        
        if j <= l or r <= i:
            return set()
        elif l <= i and j <= r:
            return self.array[k]
        else:
            l_set = self.subquery(l, r, 2 * k + 1, i, (i + j) // 2)
            r_set = self.subquery(l, r, 2 * k + 2, (i + j) // 2, j)
            return l_set | r_set

    def query(self, l, r):
        
        return len(self.subquery(l, r, 0, 0, 2**self.size))

    def update(self, i, c):
        
        tmp = i + 2**self.size - 1
        self.array[tmp] = {c}
        while tmp > 0:
            tmp = (tmp - 1) // 2
            self.array[tmp] = self.array[2 * tmp + 1] | self.array[2 * tmp + 2]


n = int(input())
S = list(input())
S = [ord(s) for s in S]
segtree = SegmentTree(S, 19)
for _ in range(int(input())):
    t, i, c = input().split()
    if t == '1':
        segtree.update(int(i)-1, ord(c))
    if t == '2':
        print(segtree.query(int(i)-1, int(c)))

Solution (Python):
class BIT:
    def __init__(self, N):
        self.tree = [0] * (N + 1)  
        self.N = N

    def add(self, i, x):
        """tree[i]と関連個所にxを加える"""
        tree = self.tree
        N = self.N
        while i <= N:
            tree[i] += x
            i += i & (-i)

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


def main():
    from string import ascii_lowercase
    import sys
    input = sys.stdin.readline

    N = int(input())
    s = input().rstrip()
    Q = int(input())

    conv = {c: i for i, c in enumerate(ascii_lowercase)}
    s = [conv[c] for c in s]

    bs = [BIT(N) for _ in range(26)]
    for i, c in enumerate(s, 1):
        bs[c].add(i, 1)

    ans = []
    for _ in range(Q):
        it = iter(input().split())
        if next(it) == '1':
            
            i = int(next(it))  
            c = conv[next(it)]

            p = s[i - 1]
            bs[p].add(i, -1)

            s[i - 1] = c
            bs[c].add(i, 1)

        else:
            
            l, r = map(int, it)
            cnt = 0
            for b in bs:
                cnt += int(b.sum(r) - b.sum(l - 1) > 0)
            ans.append(cnt)
    print(*ans, sep='\n')


if __name__ == '__main__':
    main()

Solution (Python):
from collections import defaultdict
from bisect import bisect_left, bisect_right, insort_left, insort_right
import sys
input = sys.stdin.readline


def main():
    N = int(input())
    S = list(input())
    q = int(input())
    Q = [input() for _ in range(q)]

    dd = defaultdict(list)  
    for i in range(ord('a'), ord('z') + 1):
        dd[chr(i)] = []
    for i, st in enumerate(S):
        dd[st].append(i)

    ans = []
    for q in Q:
        t, a, b = q.split()
        a = int(a) - 1
        if int(t) == 1:
            if S[a] == b: continue
            
            id = bisect_left(dd[S[a]], a)
            dd[S[a]].pop(id)  
            insort_left(dd[b], a)  
            S[a] = b
        else:
            b = int(b) - 1
            cnt = 0
            for l in dd.values():
                
                
                
                if l and a <= l[-1] and l[bisect_left(l, a)] <= b:
                    cnt += 1
            ans.append(cnt)
    print(*ans, sep='\n')

if __name__ == '__main__':
    main()

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


class SegmentTree():
    
    def __init__(self, S, n):
        self.size = n
        self.array = [set()] * (2**(self.size + 1) - 1)
        for i, c in enumerate(S):
            self.array[i + 2**self.size - 1] = {c}
        for i in range(2**self.size - 1)[::-1]:
            self.array[i] = self.array[2 * i + 1] | self.array[2 * i + 2]

    def subquery(self, l, r, k, i, j):
        
        if j <= l or r <= i:
            return set()
        elif l <= i and j <= r:
            return self.array[k]
        else:
            l_set = self.subquery(l, r, 2 * k + 1, i, (i + j) // 2)
            r_set = self.subquery(l, r, 2 * k + 2, (i + j) // 2, j)
            return l_set | r_set

    def query(self, l, r):
        
        return len(self.subquery(l, r, 0, 0, 2**self.size))

    def update(self, i, c):
        
        tmp = i + 2**self.size - 1
        self.array[tmp] = {c}
        while tmp > 0:
            tmp = (tmp - 1) // 2
            self.array[tmp] = self.array[2 * tmp + 1] | self.array[2 * tmp + 2]


def main():
    n = int(input())
    S = list(input())
    S = [ord(s) for s in S]
    segtree = SegmentTree(S, 19)
    for _ in range(int(input())):
        t, i, c = input().split()
        if t == '1':
            segtree.update(int(i)-1, ord(c))
        if t == '2':
            print(segtree.query(int(i)-1, int(c)))


main()

Solution (Python):
class SegmentTree():
    """一点更新、区間取得クエリをそれぞれO(logN)で答えるデータ構造を構築する。
    built(array)   := arrayを初期値とするセグメント木を構築する O(N)。
    update(i, val) := i番目の要素をvalに変更する。
    get_val(l, r)  := 区間[l, r)に対する二項演算の畳み込みの結果を返す。
    """
    def __init__(self, n, op, e):
        """要素数、二項演算、単位元を引数として渡す
        例) 区間最小値 SegmentTree(n, min, 10 ** 18)
            区間和     SegmentTree(n, lambda a, b : a + b, 0)
        """
        self.n = n
        self.op = op
        self.e = e
        self.size = 2 ** ((n - 1).bit_length())
        self.node = [self.e] * (2 * self.size)

    def build(self, array):
        """arrayを初期値とするセグメント木を構築する"""
        for i in range(self.n):
            self.node[self.size + i] = array[i]
        for i in range(self.size - 1, 0, -1):
            self.node[i] = self.op(self.node[i << 1], self.node[(i << 1) + 1])

    def update(self, i, val):
        """i番目の要素をvalに変更する"""
        i += self.size
        self.node[i] = val
        while i > 1:
            i >>= 1
            self.node[i] = self.op(self.node[i << 1], self.node[(i << 1) + 1])

    def get_val(self, l, r):
        """[l, r)の畳み込みの結果を返す"""
        l, r = l + self.size, r + self.size
        res_l, res_r = self.e, self.e
        while l < r:
            if l & 1:
                res_l = self.op(res_l, self.node[l])
                l += 1
            if r & 1:
                r -= 1
                res_r = self.op(self.node[r], res_r)
            l, r = l >> 1, r >> 1
        return self.op(res_l, res_r)


ALPH = "abcdefghijklmnopqrstuvwxyz"
to_int = {char: i for i, char in enumerate(ALPH)}


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

init = [0] * n
for i, char in enumerate(s):
    init[i] = 1 << to_int[char]

op = lambda a, b: a | b
st = SegmentTree(n, op, 0)
st.build(init)

for i in range(q):
    if query[i][0] == "1":
        _, ind, char = query[i]
        ind = int(ind) - 1
        st.update(ind, 1 << to_int[char])
    else:
        _, l, r = query[i]
        l, r = int(l) - 1, int(r) 
        print(bin(st.get_val(l, r)).count("1"))

Solution (Python):
def main():
    import sys
    input = sys.stdin.readline
    from bisect import bisect_left, insort_left
    N = int(input())
    S = list(input())
    Q = int(input())
    dic = {chr(i): [] for i in range(ord('a'), ord('z')+1)}
    for i in range(N):
        dic[S[i]].append(i)
    for _ in range(Q):
        query, a, c = input().split()
        if query == "1":
            i = int(a)-1
            if S[i] == c:
                continue
            ind = bisect_left(dic[S[i]], i)
            dic[S[i]].pop(ind)
            insort_left(dic[c], i)
            S[i] = c
        else:
            l, r = int(a)-1, int(c)-1
            ans = 0
            for inds in dic.values():
                if inds and l <= inds[-1] and inds[bisect_left(inds, l)] <= r:
                    ans += 1
            print(ans)

if __name__ == '__main__':
    main()

Solution (Python):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.readline
readlines = sys.stdin.buffer.readlines
sys.setrecursionlimit(10 ** 7)

from operator import or_


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


n = readline()
s = readline()
q = int(readline())
li = [1 << ord(x) - 97 for x in s[:-1]]
seg = SegmentTree(li, or_, 0)
ans = []
for _ in range(q):
    f, x, y = readline().split()
    x = int(x)
    if f == '1':
        seg.update(x - 1, 1 << ord(y) - 97)
    else:
        y = int(y)
        z = seg.find(x - 1, y)
        cnt = bin(z).count('1')
        ans.append(cnt)
print(*ans)

Solution (Python):
import sys
sys.setrecursionlimit(1 << 25)
read = sys.stdin.readline
ra = range
enu = enumerate


def read_ints():
    return list(map(int, read().split()))


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


def read_tuple(H):
    '''
    H is number of rows
    '''
    ret = []
    for _ in range(H):
        ret.append(tuple(map(int, read().split())))
    return ret


def read_col(H):
    '''
    H is number of rows
    A列、B列が与えられるようなとき
    ex1)A,B=read_col(H)    ex2) A,=read_col(H) 
    '''
    ret = []
    for _ in range(H):
        ret.append(list(map(int, read().split())))
    return tuple(map(list, zip(*ret)))


def read_matrix(H):
    '''
    H is number of rows
    '''
    ret = []
    for _ in range(H):
        ret.append(list(map(int, read().split())))
    return ret
    


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
        r += self.num
        res = self.ide
        while l < r:  
            if l & 1:
                res = self.func(res, self.tree[l - 1])
                l += 1
            if r & 1:
                r -= 1
                res = self.func(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res


MOD = 10**9 + 7
INF = 2**31  

from collections import defaultdict, Counter, deque
from operator import itemgetter
from itertools import product, permutations, combinations
from bisect import bisect_left, bisect_right  







N = read_a_int()
S = read()[:-1]
Q = read_a_int()


def char_to_26bit(c: str):
    num = ord(c) - ord('a')
    return 1 << num  


S_num = []
for s in S:
    S_num.append(char_to_26bit(s))


def segfunc(a: int, b: int):  
    return a | b


st = SegmentTree(S_num, segfunc, identity_element=0)


for _ in range(Q):
    com, *tmp = read().split()
    if com == '1':
        i, c = tmp
        st.update(int(i) - 1, char_to_26bit(c))
    else:
        l, r = map(int, tmp)
        print(bin(st.query(l - 1, r)).count('1'))

Solution (Python):
class SegmentTree:
    """
    0-indexed
    query : [L, R)
    """
    def __init__(self, size, initValue):
        self.size = 1 << (size.bit_length())  
        self.data = [initValue] * (2 * self.size - 1)
        self.initValue = initValue

    def cmpFunc(self, left, right):
        return left | right

    def build(self, rawData):
        self.data[self.size - 1: self.size - 1 + len(rawData)] = rawData
        for i in range(self.size - 1)[:: -1]:
            self.data[i] = self.cmpFunc(self.data[2 * i + 1], self.data[2 * i + 2])

    def update(self, index, value):
        index += self.size - 1
        self.data[index] = value
        while index >= 0:
            index = (index - 1) // 2
            self.data[index] = self.cmpFunc(self.data[2 * index + 1], self.data[2 * index + 2])

    def query(self, left, right):
        L = left + self.size
        R = right + self.size
        ret = self.initValue
        while L < R:
            if R & 1:
                R -= 1
                ret = self.cmpFunc(ret, self.data[R - 1])
            if L & 1:
                ret = self.cmpFunc(ret, self.data[L - 1])
                L += 1
            L >>= 1
            R >>= 1
        return ret

def cToI(s):
    return ord(s) - ord('a')

N = int(input())
S = list(map(cToI, input()))

S = [1 << s for s in S]
tree = SegmentTree(N, 0)
tree.build(S)

Q = int(input())
ans = []
for _ in range(Q):
    q1, q2, q3 = input().split()

    if q1 == '1':
        tree.update(int(q2) - 1, 1 << cToI(q3))
    else:
        ans.append(tree.query(int(q2) - 1, int(q3)))

for a in ans:
    cnt = 0
    while a > 0:
        cnt += a % 2
        a //= 2
    print(cnt)

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

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


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

li = []
for i in range(n):
    li.append(1 << ord(s[i]) - ord('a'))


ide_ele = 0


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

for _ in range(q):
    q1 = list(input().split())
    if q1[0] == '1':
        update(int(q1[1]) - 1, 1 << ord(q1[2]) - ord('a'))
    else:
        l,r = int(q1[1]), int(q1[2])
        print(bin(query(l-1,r)).count('1'))

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

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


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

li = []
for i in range(n):
    li.append(1 << ord(s[i]) - ord('a'))


ide_ele = 0


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

for _ in range(q):
    q1 = list(input().split())
    if q1[0] == '1':
        update(int(q1[1]) - 1, 1 << ord(q1[2]) - ord('a'))
    else:
        l,r = int(q1[1]), int(q1[2])
        print(bin(query(l-1,r)).count('1'))

Solution (Python):


import sys



from collections import defaultdict          















def main():
    mod = 1000000007                  
    inf = float('inf')
    sys.setrecursionlimit(10**6)    
    def input(): return sys.stdin.readline().rstrip()
    def ii():  return int(input())
    def mi():  return map(int, input().split())
    def mi_0(): return map(lambda x: int(x)-1, input().split())
    def lmi(): return list(map(int, input().split()))
    def lmi_0(): return list(map(lambda x: int(x)-1, input().split()))
    def li():  return list(input())

    
    


    class SegTree:
        def __init__(self, size):
            self.size = size
            self.n0 = 2 ** (size - 1).bit_length()
            self.table = [0 for _ in range(2 * self.n0)]
        
        def update(self, k, new_char):
            'update char in a_k to new_char'
            table_k = k + self.n0 - 1
            new_num = 1 << (ord(new_char) - ord('a'))
            if self.table[table_k] != new_num:
                self.table[table_k] = new_num
                while table_k // 2 > 0:
                    table_k //= 2
                    self.table[table_k] = self.table[2 * table_k] | self.table[2 * table_k + 1]
        
        def range_set(self, l, r):
            'return integer that represents character set appeared in a_l to a_r'
            bit_field = 0
            table_l = l + self.n0 - 1
            table_r = r + self.n0 - 1
            if table_l > table_r:
                raise RuntimeError("l should be less than or equals to r. got l:{} and r:{}".format(l, r))
            while table_l < table_r:
                if table_l & 0b1 == 1:
                    bit_field |= self.table[table_l]
                if table_r & 0b1 == 0:
                    bit_field |= self.table[table_r]
                table_l = (table_l + 1)  // 2
                table_r = (table_r - 1) // 2
            if table_l == table_r:
                bit_field |= self.table[table_l]
            return bit_field


    def execute_query(seg_tree, L, buf):
        id = int(L[0])
        if id == 1:
            i = int(L[1])
            char = L[2]
            seg_tree.update(i, char)
        else:
            i, j = map(int, L[1:])
            bit_field = seg_tree.range_set(i, j)
            buf.append(bin(bit_field)[2:].count('1'))

    n = ii()
    s = input()
    q = ii()
    commands = []
    for _ in range(q):
        commands.append(input().split())

    st = SegTree(n)
    for i, char in enumerate(s):
        st.update(i+1, char)
    
    buf = []
    for query in commands:
        execute_query(st, query, buf)
    for elm in buf:
        print(elm)


if __name__ == "__main__":
    main()

Solution (Python):
class SegmentTree():
    def segfunc(self, x, y):
        return x|y 
    
    def __init__(self, a): 
        n = len(a)
        self.ide_ele = 0 
        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] = a[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, s):
        x = 1<<(ord(s)-97)
        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

def popcount(x):
    '''xの立っているビット数をカウントする関数
    (xは64bit整数)'''

    
    x = x - ((x >> 1) & 0x5555555555555555)

    
    x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)

    x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f 
    x = x + (x >> 8) 
    x = x + (x >> 16) 
    x = x + (x >> 32) 
    return x & 0x0000007f
    

N = int(input())
S = list(input())
for i in range(N):
    S[i] = 1<<(ord(S[i])-97)
Seg = SegmentTree(S)
Q = int(input())
for i in range(Q):
    x, y, z = input().split()
    if int(x) == 1:
        Seg.update(int(y)-1, z)
    else:
        print(popcount(Seg.query(int(y)-1, int(z))))

Solution (Python):
N = int(input())
S = list(input())
Q = int(input())


class Bit:
    """1-indexed"""

    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


en2asc = lambda s: ord(s) - 97

Bits = [Bit(N) for _ in range(26)]
for i, s in enumerate(S):
    Bits[en2asc(s)].add(i + 1, 1)

for _ in range(Q):
    q = input().split()
    if q[0] == '1':
        i, c = int(q[1]), q[2]
        old = S[i - 1]
        Bits[en2asc(old)].add(i, -1)
        Bits[en2asc(c)].add(i, 1)
        S[i - 1] = c
    else:
        l, r = int(q[1]), int(q[2])
        ans = 0
        for b in Bits:
            ans += bool(b.sum(r) - b.sum(l - 1))
        print(ans)

Solution (Python):



from bisect import bisect_left, insort_left
import sys
input = sys.stdin.readline
OFS = ord('a')
_ = input()
S = list(input()[:-1])

D = [[] for _ in [0]*26]
for i, s in enumerate(S):
    D[ord(s)-OFS].append(i)

for _ in [0]*int(input()):
    Q = input()[:-1].split()
    if Q[0] == '1':
        i, c = int(Q[1])-1, Q[2]

        if S[i] != c:
            s = ord(S[i])-OFS
            D[s].pop(bisect_left(D[s], i))
            insort_left(D[ord(c)-OFS], i)
            S[i] = c

    else:
        l, r = int(Q[1])-1, int(Q[2])-1

        cnt = 0
        for L in D:
            i = bisect_left(L, l)
            if i < len(L) and L[i] <= r:
                cnt += 1

        print(cnt)