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
import math
import string
import fractions
import random
from operator import itemgetter
import itertools
from collections import deque
import copy
import heapq
import bisect

MOD = 10 ** 9 + 7
INF = float('inf')
input = lambda: sys.stdin.readline().strip()


def func(a, b):
    if a | b == 0:
        return 0
    else:
        return 1


class SegmentTree:
    """
    各ノードが半開区間に対応した完全二分木。
    子は親を半分にした区間を持つ。
    構築O(n), 区間に対する操作O(logn), 値の更新O(logn)
    区間に対する操作は最小値, 最大値, 区間に対する和など柔軟に変更して用いよう！
    """

    def __init__(self, x, init_val):  
        self.init_val = init_val
        self.length = 2 ** ((len(x) - 1).bit_length())
        self.data = [init_val] * 2 * self.length
        for i in range(len(x)):
            self.data[i + self.length - 1] = x[i]
        for i in range(self.length - 2, -1, -1):
            self.data[i] = func(self.data[2 * i + 1], self.data[2 * i + 2])

    def teach_current_val(self, index):
        return self.data[index + self.length - 1]

    def replace(self, index, val):  
        index += self.length - 1
        self.data[index] = val
        while index:
            index = (index - 1) // 2
            self.data[index] = func(self.data[2 * index + 1], self.data[2 * index + 2])

    def query(self, left, right):  
        if right <= left:
            return self.init_val
        left += self.length - 1  
        right += self.length - 2  
        ans_ = self.init_val
        while right > left + 1:
            if left & 1 == 0:  
                ans_ = func(ans_, self.data[left])
            if right & 1 == 1:  
                ans_ = func(ans_, self.data[right])
                right -= 1
            left //= 2
            right = (right - 1) // 2
        if left == right:
            ans_ = func(ans_, self.data[left])
        else:
            ans_ = func(func(ans_, self.data[left]), self.data[right])
        return ans_


N = int(input())
S = input()
Q = int(input())
alphabets = string.ascii_lowercase
segs = []
check = dict()
for i in alphabets:
    segs.append([1 if S[l] == i else 0 for l in range(N)])
for i in range(26):
    segs[i] = SegmentTree(segs[i], 0)
for _ in range(Q):
    Query = list(map(str, input().split()))
    if Query[0] == "1":
        i, c = int(Query[1]), Query[2]
        if check.get(str(i - 1)):
            segs[ord(check[str(i - 1)]) - 97].replace(i - 1, 0)
            segs[ord(c) - 97].replace(i - 1, 1)
            check[str(i - 1)] = c
        else:
            segs[ord(S[i - 1]) - 97].replace(i - 1, 0)
            segs[ord(c) - 97].replace(i - 1, 1)
            check[str(i - 1)] = c
    else:
        l, r = map(int, (Query[1], Query[2]))
        ans = 0
        for i in segs:
            ans += i.query(l - 1, r)
        print(ans)

Solution (Python):
import sys
import math
import string
import fractions
import random
from operator import itemgetter
import itertools
from collections import deque
import copy
import heapq
import bisect

MOD = 10 ** 9 + 7
INF = float('inf')
input = lambda: sys.stdin.readline().strip()


def func(a, b):
    return a+b


class SegmentTree:
    """
    各ノードが半開区間に対応した完全二分木。
    子は親を半分にした区間を持つ。
    構築O(n), 区間に対する操作O(logn), 値の更新O(logn)
    区間に対する操作は最小値, 最大値, 区間に対する和など柔軟に変更して用いよう！
    """

    def __init__(self, x, init_val):  
        self.init_val = init_val
        self.length = 2 ** ((len(x) - 1).bit_length())
        self.data = [init_val] * 2 * self.length
        for i in range(len(x)):
            self.data[i + self.length - 1] = x[i]
        for i in range(self.length - 2, -1, -1):
            self.data[i] = func(self.data[2 * i + 1], self.data[2 * i + 2])

    def teach_current_val(self, index):
        return self.data[index + self.length - 1]

    def replace(self, index, val):  
        index += self.length - 1
        self.data[index] = val
        while index:
            index = (index - 1) // 2
            self.data[index] = func(self.data[2 * index + 1], self.data[2 * index + 2])

    def query(self, left, right):  
        if right <= left:
            return self.init_val
        left += self.length - 1  
        right += self.length - 2  
        ans_ = self.init_val
        while right > left + 1:
            if left & 1 == 0:  
                ans_ = func(ans_, self.data[left])
            if right & 1 == 1:  
                ans_ = func(ans_, self.data[right])
                right -= 1
            left //= 2
            right = (right - 1) // 2
        if left == right:
            ans_ = func(ans_, self.data[left])
        else:
            ans_ = func(func(ans_, self.data[left]), self.data[right])
        return ans_


N = int(input())
S = input()
Q = int(input())
alphabets = string.ascii_lowercase
segs = []
check = dict()
for i in alphabets:
    segs.append([1 if S[l] == i else 0 for l in range(N)])
for i in range(26):
    segs[i] = SegmentTree(segs[i], 0)
for _ in range(Q):
    Query = list(map(str, input().split()))
    if Query[0] == "1":
        i, c = int(Query[1]), Query[2]
        if check.get(str(i - 1)):
            segs[ord(check[str(i - 1)]) - 97].replace(i - 1, 0)
            segs[ord(c) - 97].replace(i - 1, 1)
            check[str(i - 1)] = c
        else:
            segs[ord(S[i - 1]) - 97].replace(i - 1, 0)
            segs[ord(c) - 97].replace(i - 1, 1)
            check[str(i - 1)] = c
    else:
        l, r = map(int, (Query[1], Query[2]))
        ans = 0
        for i in segs:
            if i.query(l-1, r) > 0:
                ans += 1
        print(ans)

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


def Alp(s):
    return ord(s)-ord("a")


if __name__ == "__main__":
    N = int(input())
    S = list(input())
    Q = int(input())

    bit = [BinaryIndexTree(N) for _ in range(26)]
    for i, s in enumerate(S, start=1):
        bit[Alp(s)].add(i, 1)

    ans = []
    for _ in range(Q):
        q = input().split()
        if q[0] == "1":
            i = int(q[1]) - 1
            c = q[2]

            bit[Alp(c)].add(i+1, 1)
            bit[Alp(S[i])].add(i+1, -1)
            S[i] = c
        else:
            l = int(q[1])
            r = int(q[2])
            tmp = 0
            for i in range(26):
                b = bit[i]
                if b.sum(r) - b.sum(l - 1) > 0:
                    tmp += 1
            ans.append(tmp)

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

Solution (Python):
N = int(input())
S = input()
Q = int(input())
qs = [input().split() for i in range(Q)]

def ctoi(c):
    return ord(c) - ord('a')

class BinaryIndexedTree:
    def __init__(self,size):
        self.N = size
        self.bit = [0]*(size+1)
    def add(self,x,w): 
        x += 1
        while x <= self.N:
            self.bit[x] += w
            x += (x & -x)
    def _sum(self,x): 
        ret = 0
        while x > 0:
            ret += self.bit[x]
            x -= (x & -x)
        return ret
    def sum(self,l,r): 
        return self._sum(r) - self._sum(l)
    def __str__(self): 
        arr = [self.sum(i,i+1) for i in range(self.N)]
        return str(arr)
bits = [BinaryIndexedTree(N) for i in range(26)]

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

ans = []
for a,b,c in qs:
    if a=='1':
        i = int(b)-1
        bits[ctoi(s[i])].add(i,-1)
        bits[ctoi(c)].add(i,1)
        s[i] = c
    else:
        l,r = int(b)-1,int(c)
        a = 0
        for i in range(26):
            if bits[i].sum(l,r):
                a += 1
        ans.append(a)
print(*ans,sep='\n')

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

n = int(input())
s = str(input())
A = list(s)
A = A[0:n]

A = [{ord(c)-ord('a')} for c in A]


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[2*k+1], seg[2*k+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%2 == 0:
            res = segfunc(res, seg[p])
        if q%2 == 1:
            res = segfunc(res, seg[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = segfunc(res, seg[p])
    else:
        res = segfunc(segfunc(res, seg[p]), seg[q])
    return res


ide_ele = set()


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

init(A)

q = int(input())

for _ in range(q):
    c, x, y = map(str, input().split())
    if c == '1':
        x = int(x)-1
        y = {ord(y)-ord('a')}
        update(x, y)
    else:
        l = int(x)-1
        r = int(y)-1
        print(len(query(l, r+1)))

Solution (Python):
import sys
def main():
    input = sys.stdin.readline
    N = int(input())
    S = input().rstrip()
    S = [conv(c) for c in S]
    segtree = SegmentTree(initial_values=S, f=lambda x,y:x|y)

    Q = int(input())
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1':
            a = int(a) - 1
            segtree.set_val(a, conv(b))
        else:
            a, b = int(a) - 1, int(b)
            q = segtree.query(a, b)
            print(popcount(q))

def conv(c): return 1 << (ord(c) - ord('a'))
def popcount(x):
    x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555)
    x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333)
    x = x + (x >> 4) & 0x0f0f0f0f0f0f0f0f
    x += x >> 8
    x += x >> 16
    x += x >> 32
    return x & 0x7f

class SegmentTree:
    def __init__(self, n=None, f=max, identity_factory=int, initial_values=None):
        assert(n or initial_values)
        size = n if n else len(initial_values)
        d = [identity_factory() for _ in range(2 * size + 1)]
        self.__n, self.__d, self.__f, self.__e = size, d, f, identity_factory
        if initial_values:
            for i, v in enumerate(initial_values): d[size + i] = v
            for i in range(size - 1, 0, -1): d[i] = f(d[i<<1], d[i<<1|1])

    def get_val(self, index):
        return self.__d[index + self.__n]

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

    def modify(self, index, value):
        self.set_val(index, self.__f(self.__d[index + self.__n], value))

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

    def bisect_left(self, func):
        '''func()がFalseになるもっとも左のindexを探す
        '''
        i, n, f, d, v = 1, self.__n, self.__f, self.__d, self.__e()
        while i < n:
            if func(f(v, d[i<<1])): v, i = f(v, d[i<<1]), i<<1|1
            else: i = i<<1
        return i - n


if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.readline
class Bit:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)
 
    def sum(self, i):
        s = 0
        while i > 0:       
            s += self.tree[i] 
            i -= i & -i       
        return s                            
                                            
    def add(self, i, x):                  
        while i <= self.size:
            self.tree[i] += x  
            i += i & -i
x = "abcdefghijklmnopqrstuvwxyz"
N, = map(int, input().split())
d = dict()
for c in x:
    d[c] = Bit(N+1)

S = list(input().strip())
for i, c in enumerate(S):
    d[c].add(i+1, 1)

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

Solution (Python):
from collections import defaultdict
import bisect

n = int(input())
s = input()
S = []
cnt_ch = defaultdict(list)
for i in range(n):
    S.append(s[i])
    cnt_ch[s[i]].append(i)
    
    
    
    
q = int(input())
for i in range(q):
    qw = input()
    if qw[0] == "1":
        qw = qw[2:]
        i, ch = map(str, qw.split())
        if S[int(i) - 1] == ch:
            continue
        remove = bisect.bisect_left(cnt_ch[S[int(i) - 1]], int(i) - 1)
        del cnt_ch[S[int(i) - 1]][remove]
        S[int(i) - 1] = ch
        if not cnt_ch[ch]:
            cnt_ch[ch].append(int(i) - 1)
            continue
        bisect.insort_left(cnt_ch[ch], int(i) - 1)
        
        
    else:
        
        qw = qw[2:]
        l, r = map(int, qw.split())
        cnt = 0
        for i in range(ord("a"),ord("a") + 26):
            if not cnt_ch[chr(i)]:
                continue
            edge = bisect.bisect_left(cnt_ch[chr(i)], l - 1)
            
            
            
            
            
            if edge < len(cnt_ch[chr(i)]):
                if cnt_ch[chr(i)][edge] < r:
                    cnt += 1
            
        print(cnt)

Solution (Python):
import sys
input = sys.stdin.readline
N = int(input())
S = input().rstrip()
Q = int(input())
qs = [input().split() for i in range(Q)]

def ctoi(c):
    return ord(c) - ord('a')

class BinaryIndexedTree:
    def __init__(self,size):
        self.N = size
        self.bit = [0]*(size+1)
    def add(self,x,w): 
        x += 1
        while x <= self.N:
            self.bit[x] += w
            x += (x & -x)
    def _sum(self,x): 
        ret = 0
        while x > 0:
            ret += self.bit[x]
            x -= (x & -x)
        return ret
    def sum(self,l,r): 
        return self._sum(r) - self._sum(l)
bits = [BinaryIndexedTree(N) for _ in range(26)]

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

s = list(S)
ans = []
for a,b,c in qs:
    if a=='1':
        x = int(b)-1
        bits[ctoi(c)].add(x,1)
        bits[ctoi(s[x])].add(x,-1)
        s[x] = c
    else:
        b,c = int(b)-1,int(c)
        tmp = 0
        for i in range(26):
            if bits[i].sum(b,c) > 0:
                tmp += 1
        ans.append(tmp)
print(*ans, sep='\n')

Solution (Python):
import sys
input = sys.stdin.readline
N = int(input())
S = input().rstrip()
Q = int(input())
qs = [input().split() for i in range(Q)]

def ctoi(c):
    return ord(c) - ord('a')

class BinaryIndexedTree:
    def __init__(self,size):
        self.N = size
        self.bit = [0]*(size+1)
    def add(self,x,w):
        x += 1
        while x <= self.N:
            self.bit[x] += w
            x += (x & -x)
    def _sum(self,x):
        x += 1
        ret = 0
        while x > 0:
            ret += self.bit[x]
            x -= (x & -x)
        return ret
    def sum(self,l,r):
        return self._sum(r-1) - self._sum(l-1)
bits = [BinaryIndexedTree(N) for _ in range(26)]

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

s = list(S)
ans = []
for a,b,c in qs:
    if a=='1':
        x = int(b)-1
        bits[ctoi(c)].add(x,1)
        bits[ctoi(s[x])].add(x,-1)
        s[x] = c
    else:
        b,c = int(b)-1,int(c)
        tmp = 0
        for i in range(26):
            if bits[i].sum(b,c) > 0:
                tmp += 1
        ans.append(tmp)
print(*ans, sep='\n')

Solution (Python):
import sys
input = sys.stdin.readline
N = int(input())
S = input().rstrip()
Q = int(input())
qs = [input().split() for i in range(Q)]

def ctoi(c):
    return ord(c) - ord('a')

class BinaryIndexedTree:
    def __init__(self,size):
        self.N = size
        self.bit = [0]*(size+1)
    def add(self,x,w):
        x += 1
        while x <= self.N:
            self.bit[x] += w
            x += (x & -x)
    def sum(self,x):
        x += 1
        ret = 0
        while x > 0:
            ret += self.bit[x]
            x -= (x & -x)
        return ret
bits = [BinaryIndexedTree(N) for _ in range(26)]

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

s = list(S)
ans = []
for a,b,c in qs:
    if a=='1':
        x = int(b)-1
        bits[ctoi(c)].add(x,1)
        bits[ctoi(s[x])].add(x,-1)
        s[x] = c
    else:
        b,c = int(b)-1,int(c)-1
        tmp = 0
        for i in range(26):
            if bits[i].sum(c) - bits[i].sum(b-1) > 0:
                tmp += 1
        ans.append(tmp)
print(*ans, sep='\n')

Solution (Python):
import sys
input = sys.stdin.readline
N = int(input())
S = input().rstrip()
Q = int(input())
qs = [input().split() for i in range(Q)]

def ctoi(c):
    return ord(c) - ord('a')

class BinaryIndexedTree:
    def __init__(self,size):
        self.N = size
        self.bit = [0]*(size+1)
    def add(self,x,w):
        while x <= self.N:
            self.bit[x] += w
            x += (x & -x)
    def sum(self,x):
        ret = 0
        while x > 0:
            ret += self.bit[x]
            x -= (x & -x)
        return ret
bits = [BinaryIndexedTree(N) for _ in range(26)]

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

s = list(S)
ans = []
for a,b,c in qs:
    if a=='1':
        x = int(b)
        bits[ctoi(c)].add(x,1)
        bits[ctoi(s[x-1])].add(x,-1)
        s[x-1] = c
    else:
        tmp = 0
        for i in range(26):
            if bits[i].sum(int(c)) - bits[i].sum(int(b)-1) > 0:
                tmp += 1
        ans.append(tmp)
print(*ans, sep='\n')

Solution (Python):
import bisect
import sys
def input(): return sys.stdin.readline().rstrip()

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

char_idx = [[] for _ in range(26)]
for i in range(n):
    char_idx[ord(s[i])-ord('a')].append(i)


query = [input().split() for _ in range(q)]


for t, a, b in query:
    if t=='1':
        i = int(a) - 1
        if s[i] == b:
            continue
        else:
            idx = bisect.bisect_left(char_idx[ord(s[i])-ord('a')], i)
            if char_idx[ord(s[i])-ord('a')][idx] == i:
                del char_idx[ord(s[i])-ord('a')][idx]
            bisect.insort_left(char_idx[ord(b)-ord('a')], i)
            s[i] = b
    else:
        l = int(a) - 1
        r = int(b) - 1
        ans = 0
        for i in range(26):
            if len(char_idx[i]) == 0:
                continue
            it = bisect.bisect_left(char_idx[i], l)
            if it < len(char_idx[i]) and char_idx[i][it] <= r:
                ans += 1
        print(ans)

Solution (Python):
"""
AtCoder Beginner Contest 157  E - Simple String Queries

文字列Sに対して、
クエリ1：i番目の文字をcに変更
クエリ2：S[l~r]に何種類の文字があるか

各クエリについて、律儀に文字を変えて、l~rについて何種類あるか調べると間に合わないはず。

~~~ABCCDC~~~
        ↑を別の文字にした時に、最後に出てくるCがその二個左、のような情報をちゃんと残したい。
→ 最後の位置が知りたいとかではなく、lとrを指定した時に、その間にあるかが知りたい（具体的な位置が知りたいわけではない）
　そうするt、a〜zについて、l~rに存在するか、みたいな確認ができそう

N <= 5 * 10**5
Q <= 2 * 10**4
なので、bisect使えば間に合うのか？よくわからん

Sとしてではなく、現時点で何文字目がなになのかも持っておいたほうが楽か。

"""

import bisect

N = int(input())
S = input()
Q = int(input())


cS = [""] * N

char_idxs = [[]for _  in range(26)]


for i,s in enumerate(S):
    cS[i] = s
    char_idxs[ord(s) - 97].append(i)

query = [tuple(map(str, input().split())) for _ in range(Q)]




for q,a,b in query:
    
    
    if q == "1":
        
        if cS[int(a) - 1] == b:
            continue
        else:
            
            

            
            idx = bisect.bisect_right(char_idxs[ord(cS[int(a)-1]) - 97], int(a)-1)
            
            if char_idxs[ord(cS[int(a)-1]) - 97][idx-1] == int(a)-1:
                
                char_idxs[ord(cS[int(a)-1]) - 97][idx-1:idx] = []
            
            
            bisect.insort_right(char_idxs[ord(b) - 97], int(a) - 1)

            
            cS[int(a) - 1] = b

    
    else:
        cnt = 0
        for i in range(26):
            
            if len(char_idxs[i]) == 0: continue
            
            l = bisect.bisect_left(char_idxs[i], int(a)-1)
            

            
            if l < len(char_idxs[i]) and char_idxs[i][l] <= int(b)-1:
                cnt += 1

        print(cnt)

Solution (Python):

import bisect

N = int(input())
S = input()
Q = int(input())


cS = [""] * N

char_idxs = [[]for _  in range(26)]


for i,s in enumerate(S):
    cS[i] = s
    char_idxs[ord(s) - 97].append(i)

query = [tuple(map(str, input().split())) for _ in range(Q)]




for q,a,b in query:
    
    
    if q == "1":
        
        if cS[int(a) - 1] == b:
            continue
        else:
            
            

            
            idx = bisect.bisect_right(char_idxs[ord(cS[int(a)-1]) - 97], int(a)-1)
            
            if char_idxs[ord(cS[int(a)-1]) - 97][idx-1] == int(a)-1:
                
                char_idxs[ord(cS[int(a)-1]) - 97][idx-1:idx] = []
            
            
            bisect.insort_right(char_idxs[ord(b) - 97], int(a) - 1)

            
            cS[int(a) - 1] = b

    
    else:
        cnt = 0
        for i in range(26):
            
            if len(char_idxs[i]) == 0: continue
            
            l = bisect.bisect_left(char_idxs[i], int(a)-1)
            

            
            if l < len(char_idxs[i]) and char_idxs[i][l] <= int(b)-1:
                cnt += 1

        print(cnt)

Solution (Python):
import sys;input=sys.stdin.readline
n=int(input())
s=input()
num=2**(n-1).bit_length()
def segfunc(x,y):return x|y
seg=[0]*(2*num-1)
for i in range(n):seg[i+num-1]=2**(ord(s[i])-97)
for i in range(num-2,-1,-1):seg[i]=segfunc(seg[2*i+1],seg[2*i+2])
def update(i,x):
  i+=num-1;seg[i]=x
  while i:i=(i-1)//2;seg[i]=segfunc(seg[i*2+1],seg[i*2+2])
def query(l,r):
  l+=num-1;r+=num-1
  if l==r:return seg[l]
  s=seg[l];l+=1
  while r-l>1:
    if ~l%2:s=segfunc(seg[l],s)
    if r%2:s=segfunc(seg[r],s);r-=1
    l//=2;r=(r-1)//2
  if l==r:return segfunc(s,seg[l])
  return segfunc(s,segfunc(seg[l],seg[r]))
for _ in range(int(input())):
  quer=input().split()
  if quer[0]=="1":
    _,i,c=quer
    update(int(i)-1,2**(ord(c)-97))
  else:
    _,l,r=quer
    print(sum(map(int,bin(query(int(l)-1,int(r)-1))[2:])))

Solution (Python):
import sys;input=sys.stdin.readline
n=int(input())
s=input()
num=2**(n-1).bit_length()
def segfunc(x,y):return x|y
seg=[0]*(2*num-1)
for i in range(n):seg[i+num-1]=2**(ord(s[i])-97)
for i in range(num-2,-1,-1):seg[i]=segfunc(seg[2*i+1],seg[2*i+2])
def update(i,x):
  i+=num-1;seg[i]=x
  while i:i=(i-1)//2;seg[i]=segfunc(seg[i*2+1],seg[i*2+2])
def query(l,r):
  l+=num-1;r+=num-1
  if l==r:return seg[l]
  s=seg[l];l+=1
  while r-l>1:
    if ~l%2:s=segfunc(seg[l],s)
    if r%2:s=segfunc(seg[r],s);r-=1
    l//=2;r=(r-1)//2
  if l==r:return segfunc(s,seg[l])
  return segfunc(s,segfunc(seg[l],seg[r]))
for _ in range(int(input())):
  quer=input().split()
  if quer[0]=="1":
    _,i,c=quer
    update(int(i)-1,2**(ord(c)-97))
  else:
    _,l,r=quer
    print(sum(map(int,bin(query(int(l)-1,int(r)-1))[2:])))

Solution (Python):
def main():
  import sys
  b=sys.stdin.buffer
  input=b.readline
  n=int(input())
  d=[set()for _ in range(n)]+[{c}for c in input()]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  add=r.append
  input()
  for q,a,b in zip(*[iter(b.read().split())]*3):
    i=int(a)+n-1
    if q<b'2':
      d[i]={b[0]}
      while i:
        i>>=1
        d[i]=d[i+i]|d[i-~i]
      continue
    j=int(b)+n
    s=set()
    while i<j:
      if i&1:
        s|=d[i]
        i+=1
      if j&1:
        j-=1
        s|=d[j]
      i>>=1
      j>>=1
    add(len(s))
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  b=sys.stdin.buffer
  input=b.readline
  n=int(input())
  d=[0]*n+[1<<c-97for c in input()[:n]]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  add=r.append
  input()
  for q,a,b in zip(*[iter(b.read().split())]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i>>=1
        d[i]=d[i+i]|d[i-~i]
      continue
    j=int(b)+n
    while i<j:
      if i&1:
        s|=d[i]
        i+=1
      if j&1:
        j-=1
        s|=d[j]
      i>>=1
      j>>=1
    add(bin(s).count('1'))
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  b=sys.stdin.buffer
  input=b.readline
  n=int(input())
  d=[0]*n+[1<<c-97for c in input()[:n]]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  input()
  for q,a,b in zip(*[iter(b.read().split())]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i>>=1
        d[i]=d[i+i]|d[i-~i]
      continue
    j=int(b)+n
    while i<j:
      if i&1:
        s|=d[i]
        i+=1
      if j&1:
        j-=1
        s|=d[j]
      i>>=1
      j>>=1
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  b=sys.stdin.buffer
  input=b.readline
  n=int(input())
  d=[0]*n+[1<<c-97for c in input()[:n]]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  input()
  for q,a,b in zip(*[iter(b.read().split())]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    j=int(b)+n
    while i<j:
      if i%2:
        s|=d[i]
        i+=1
      if j%2:
        j-=1
        s|=d[j]
      i//=2
      j//=2
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  b=sys.stdin.buffer
  input=b.readline
  n=int(input())
  d=[0]*n+[1<<c-97for c in input()[:n]]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  input()
  for q,a,b in zip(*[iter(b.read().split())]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  input=sys.stdin.buffer.readline
  n=int(input())
  d=[0]*n+[1<<c-97for c in input()[:n]]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  for _ in range(int(input())):
    q,a,b=input().split()
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  n,s,_,*t=sys.stdin.buffer.read().split()
  n=int(n)
  d=[0]*n+[1<<c-97for c in s]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  for q,a,b in zip(*[iter(t)]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  n,s,_,*t=sys.stdin.buffer.read().split()
  n=int(n)
  d=[0]*n+[1<<c-97for c in s]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  for q,a,b in zip(*[iter(t)]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      j=1<<b[0]-97
      if d[i]==j:continue
      d[i]=j
      while i>1:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  n,s,_,*t=sys.stdin.buffer.read().split()
  n=int(n)
  d=[0]*n+[1<<c-97for c in s]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i+i+1]
  r=[]
  for q,a,b in zip(*[iter(t)]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i>1:
        i//=2
        d[i]=d[i+i]|d[i+i+1]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  n,s,_,*t=sys.stdin.buffer.read().split()
  n=int(n)
  d=[0]*n+[2**(c-97)for c in s]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  for q,a,b in zip(*[iter(t)]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=2**(b[0]-97)
      while i>1:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()

Solution (Python):
def main():
  import sys
  n,s,_,*t=sys.stdin.buffer.read().split()
  n=int(n)
  d=[0]*n+[1<<c-97for c in s]
  for i in range(n-1,0,-1):d[i]=d[i+i]|d[i-~i]
  r=[]
  for q,a,b in zip(*[iter(t)]*3):
    i,s=int(a)+n-1,0
    if q<b'2':
      d[i]=1<<b[0]-97
      while i>1:
        i//=2
        d[i]=d[i+i]|d[i-~i]
      continue
    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
    r+=bin(s).count('1'),
  print(' '.join(map(str,r)))
main()